Manage Appointments DONE!

This commit is contained in:
andrei-mihnea-cerbu
2024-04-08 21:29:18 +03:00
parent 8663a186a0
commit 13bfa2bdd9
91 changed files with 762 additions and 52 deletions
@@ -0,0 +1,38 @@
using Application.Endpoints;
using Application.Endpoints.Appointments;
using Application.Services.Database;
using Application.Services.Database.MongoDB;
using Microsoft.AspNetCore.Mvc;
namespace API.Controllers;
public class AppointmentsController : BaseApiController
{
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
private readonly IPatientRepository _patientRepository;
private readonly IDoctorRepository _doctorRepository;
public AppointmentsController(IAppointmentsMongoDbService appointmentsMongoDbService,
IPatientRepository patientRepository, IDoctorRepository doctorRepository)
{
_appointmentsMongoDbService = appointmentsMongoDbService;
_patientRepository = patientRepository;
_doctorRepository = doctorRepository;
}
[HttpPost]
public async Task<ActionResult<BaseResponse>> CreateAppointment(AppointmentManagementDto dto)
{
var handler = new AppointmentManagementHandler(_appointmentsMongoDbService, _patientRepository, _doctorRepository);
var response = await handler.HandleCreateAppointment(dto).ConfigureAwait(false);
return StatusCode(response.StatusCode, response);
}
[HttpDelete]
public async Task<ActionResult<BaseResponse>> DeleteAppointment(AppointmentManagementDto dto)
{
var handler = new AppointmentManagementHandler(_appointmentsMongoDbService, _patientRepository, _doctorRepository);
var response = await handler.HandleDeleteAppointment(dto).ConfigureAwait(false);
return StatusCode(response.StatusCode, response);
}
}
+26 -1
View File
@@ -4,6 +4,7 @@ using Application.Endpoints.Doctors.Profile;
using Application.Endpoints.Doctors.Registration;
using Application.Endpoints.Doctors.ResetPassword;
using Application.Services.Database;
using Application.Services.Database.MongoDB;
using Application.Services.HashingAlgorithms;
using Application.Services.Jwt;
using Core.Entities;
@@ -18,13 +19,15 @@ public class DoctorsController : ControllerBase
private readonly IDoctorRepository _database;
private readonly IHashingAlgorithms _hashingAlgorithms;
private readonly IJwtService _jwtService;
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
public DoctorsController(IDoctorRepository database, IHashingAlgorithms hashingAlgorithms,
IJwtService jwtService)
IJwtService jwtService, IAppointmentsMongoDbService appointmentsMongoDbService)
{
_database = database;
_hashingAlgorithms = hashingAlgorithms;
_jwtService = jwtService;
_appointmentsMongoDbService = appointmentsMongoDbService;
}
[HttpPost("register")]
@@ -40,6 +43,7 @@ public class DoctorsController : ControllerBase
{
var handler = new DoctorLoginHandler(_database, _hashingAlgorithms);
var response = await handler.Handle(doctorLoginDto).ConfigureAwait(false);
/*
if (response.Data != null)
{
Doctor doctor = (Doctor)response.Data;
@@ -47,6 +51,7 @@ public class DoctorsController : ControllerBase
HttpContext.Response.Headers.Add("Authorization", $"Bearer {authToken}");
}
*/
return StatusCode(response.StatusCode, response);
}
@@ -125,6 +130,26 @@ public class DoctorsController : ControllerBase
{
var handler = new DoctorProfileHandler(_database, _hashingAlgorithms);
var response = await handler.HandleDelete(id).ConfigureAwait(false);
if (response.StatusCode < HttpStatusCodes.BadRequest)
{
DeleteDoctorAppointments(id);
}
return StatusCode(response.StatusCode, response);
}
private async void DeleteDoctorAppointments(Guid doctorId)
{
var criteria = new List<(string FieldName, string Value)>
{
("DoctorId", doctorId.ToString())
};
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
if (!appointments.Any())
{
return;
}
await _appointmentsMongoDbService.DeleteByIdAsync<Appointment>(appointments[0].Id);
}
}
@@ -48,6 +48,7 @@ public class PatientsController : ControllerBase
{
var handler = new PatientLoginHandler(_patientRepository);
var response = await handler.Handle(patientLoginDto).ConfigureAwait(false);
/*
if (response.Data != null)
{
Patient patient = (Patient)response.Data;
@@ -55,6 +56,7 @@ public class PatientsController : ControllerBase
HttpContext.Response.Headers.Add("Authorization", $"Bearer {authToken}");
}
*/
return StatusCode(response.StatusCode, response);
}
+12 -12
View File
@@ -53,18 +53,18 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
// .AddJwtBearer(options =>
// {
// options.TokenValidationParameters = new TokenValidationParameters
// {
// ValidateIssuerSigningKey = true,
// IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])),
// ValidateIssuer = false,
// ValidateAudience = false,
// ClockSkew = TimeSpan.Zero
// };
// });
app.MapControllers();
+3 -2
View File
@@ -12,7 +12,8 @@
"HealthcareManagerDatabase": {
"Name": "HealthcareManager",
"MedicalRecordCollectionName": "MedicalHistory",
"ChatCollectionName": "Chat"
"ChatCollectionName": "Chat",
"AppointmentsCollectionName": "Appointments"
},
"ApiKeySettings": {
"ApiKey": "testapikey"
@@ -21,7 +22,7 @@
"SecretKey": "HealthcareManagerJwtKey",
"Issuer": "HealthcareManager",
"Audience": "HealthCareManagerUsers",
"ExpirationMinutes": 1440
"ExpirationTime": 1440
},
"AllowedHosts": "*"
}
+148 -1
View File
@@ -10,6 +10,7 @@
"dependencies": {
"Application": "1.0.0",
"Infrastructure": "1.0.0",
"Microsoft.AspNetCore.Authentication.JwtBearer": "8.0.3",
"Swashbuckle.AspNetCore": "6.5.0"
},
"runtime": {
@@ -54,6 +55,17 @@
}
}
},
"Microsoft.AspNetCore.Authentication.JwtBearer/8.0.3": {
"dependencies": {
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.1.2"
},
"runtime": {
"lib/net8.0/Microsoft.AspNetCore.Authentication.JwtBearer.dll": {
"assemblyVersion": "8.0.3.0",
"fileVersion": "8.0.324.11615"
}
}
},
"Microsoft.EntityFrameworkCore/8.0.3": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "8.0.3",
@@ -185,6 +197,71 @@
}
},
"Microsoft.Extensions.Primitives/8.0.0": {},
"Microsoft.IdentityModel.Abstractions/7.5.1": {
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.Logging/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.Protocols/7.1.2": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "7.5.1",
"Microsoft.IdentityModel.Tokens": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.dll": {
"assemblyVersion": "7.1.2.0",
"fileVersion": "7.1.2.41121"
}
}
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.1.2": {
"dependencies": {
"Microsoft.IdentityModel.Protocols": "7.1.2",
"System.IdentityModel.Tokens.Jwt": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
"assemblyVersion": "7.1.2.0",
"fileVersion": "7.1.2.41121"
}
}
},
"Microsoft.IdentityModel.Tokens/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.NETCore.Platforms/5.0.0": {},
"Microsoft.OpenApi/1.2.3": {
"runtime": {
@@ -350,6 +427,18 @@
}
},
"System.Buffers/4.5.1": {},
"System.IdentityModel.Tokens.Jwt/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "7.5.1",
"Microsoft.IdentityModel.Tokens": "7.5.1"
},
"runtime": {
"lib/net8.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"System.Memory/4.5.5": {},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {},
"System.Security.AccessControl/5.0.0": {
@@ -400,8 +489,10 @@
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Configuration.Json": "8.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0",
"Microsoft.IdentityModel.Tokens": "7.5.1",
"MongoDB.Driver": "2.24.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "8.0.2"
"Npgsql.EntityFrameworkCore.PostgreSQL": "8.0.2",
"System.IdentityModel.Tokens.Jwt": "7.5.1"
},
"runtime": {
"Infrastructure.dll": {}
@@ -443,6 +534,13 @@
"path": "fluentvalidation/11.9.0",
"hashPath": "fluentvalidation.11.9.0.nupkg.sha512"
},
"Microsoft.AspNetCore.Authentication.JwtBearer/8.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VsDy8R6/0ushSpUow7m4lB82ovVBnI1e2AtPo1z22pzYzUjqY9QJvaexzqMkwmI3K1CVdT6MweXiWoqCcHrJbA==",
"path": "microsoft.aspnetcore.authentication.jwtbearer/8.0.3",
"hashPath": "microsoft.aspnetcore.authentication.jwtbearer.8.0.3.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore/8.0.3": {
"type": "package",
"serviceable": true,
@@ -597,6 +695,48 @@
"path": "microsoft.extensions.primitives/8.0.0",
"hashPath": "microsoft.extensions.primitives.8.0.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PT16ZFbPIiMsYv07oy3zOjqUOJ7xutGBkJTOX0+IbNyU6+O6X7aIxjq9EaSSRLWbekRgamgtmfg8Xjw6A6Ua9g==",
"path": "microsoft.identitymodel.abstractions/7.5.1",
"hashPath": "microsoft.identitymodel.abstractions.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-93CGSa8RPdZU8zfvA3nf9NGKUqEnQrE12VzYlMqKh72ddhzusosqLNEUgH/YhFWBLRFOnY1RCgHMV7pR+sAx2w==",
"path": "microsoft.identitymodel.jsonwebtokens/7.5.1",
"hashPath": "microsoft.identitymodel.jsonwebtokens.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PnpAQX20BAiDIPYmWUyQSlEaWD8BLXzHpiDGTCT568Cs0ReOeyzNe401LzCeiv6ilug/KefVeV1CeqtCHTo8dw==",
"path": "microsoft.identitymodel.logging/7.5.1",
"hashPath": "microsoft.identitymodel.logging.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols/7.1.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SydLwMRFx6EHPWJ+N6+MVaoArN1Htt92b935O3RUWPY1yUF63zEjvd3lBu79eWdZUwedP8TN2I5V9T3nackvIQ==",
"path": "microsoft.identitymodel.protocols/7.1.2",
"hashPath": "microsoft.identitymodel.protocols.7.1.2.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.1.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6lHQoLXhnMQ42mGrfDkzbIOR3rzKM1W1tgTeMPLgLCqwwGw0d96xFi/UiX/fYsu7d6cD5MJiL3+4HuI8VU+sVQ==",
"path": "microsoft.identitymodel.protocols.openidconnect/7.1.2",
"hashPath": "microsoft.identitymodel.protocols.openidconnect.7.1.2.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Q3DKpyFViP84IUlTFKH/zIkswIrmSh2Vd/eFDo4wlOHy4DYxoweZEEw4kDEiKt9VCX6o7SddK3HK2xDYyFpexA==",
"path": "microsoft.identitymodel.tokens/7.5.1",
"hashPath": "microsoft.identitymodel.tokens.7.5.1.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
@@ -709,6 +849,13 @@
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UUw+E0R73lZLlXgneYIJQxNs1kfbcxjVzw64JQyiwjqCd4HMpAbjn+xRo86QZT84uHq8/MkqvfH82tgjgPzpuw==",
"path": "system.identitymodel.tokens.jwt/7.5.1",
"hashPath": "system.identitymodel.tokens.jwt.7.5.1.nupkg.sha512"
},
"System.Memory/4.5.5": {
"type": "package",
"serviceable": true,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,10 +12,17 @@
"HealthcareManagerDatabase": {
"Name": "HealthcareManager",
"MedicalRecordCollectionName": "MedicalHistory",
"ChatCollectionName": "Chat"
"ChatCollectionName": "Chat",
"AppointmentsCollectionName": "Appointments"
},
"ApiKeySettings": {
"ApiKey": "testapikey"
},
"Jwt": {
"SecretKey": "HealthcareManagerJwtKey",
"Issuer": "HealthcareManager",
"Audience": "HealthCareManagerUsers",
"ExpirationTime": 1440
},
"AllowedHosts": "*"
}
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("API")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+116405bd75830f3dec1c68562965bc78967039d5")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8663a186a056b0dfbfeebf9ae16be42b40101093")]
[assembly: System.Reflection.AssemblyProductAttribute("API")]
[assembly: System.Reflection.AssemblyTitleAttribute("API")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
cef1c0cc4ccce44108fa880ecec8ba436aa9584f61400f2f44f2970c2d6842dc
a61f57beead854c5be97ca0cf9336ea23b19a3b596fd07a95a410574950b1887
@@ -1 +1 @@
06fc5bd1554959a9b32bbdb9ef6b3f86b090ac26bcc67914d438a39ee322e613
8e2d63c970dcfcf7fa32f83c388855a8383f3ed35cc314f5089a54d4a7d74fa6
@@ -56,3 +56,11 @@ C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\FluentValidation.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Application.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Application.pdb
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.Abstractions.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.JsonWebTokens.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.Logging.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\Microsoft.IdentityModel.Tokens.dll
C:\Users\Andrei Cerbu\Documents\FACULTATE\CC-FinalProj\backend\API\bin\Debug\net8.0\System.IdentityModel.Tokens.Jwt.dll
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/48eb2adcbd149cd66c77ba558f492179d2bf29be/*"}}
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/8663a186a056b0dfbfeebf9ae16be42b40101093/*"}}
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
namespace Application.Endpoints.Appointments;
public class AppointmentManagementDto
{
public Guid DoctorId { get; set; }
public Guid PatientId { get; set; }
public DateTime Appointment { get; set; }
}
@@ -0,0 +1,121 @@
using Application.Services.Database;
using Application.Services.Database.MongoDB;
using Core.Entities;
namespace Application.Endpoints.Appointments;
public class AppointmentManagementHandler
{
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
private readonly IPatientRepository _patientRepository;
private readonly IDoctorRepository _doctorRepository;
public AppointmentManagementHandler(IAppointmentsMongoDbService appointmentsMongoDbService,
IPatientRepository patientRepository, IDoctorRepository doctorRepository)
{
_appointmentsMongoDbService = appointmentsMongoDbService;
_patientRepository = patientRepository;
_doctorRepository = doctorRepository;
}
public async Task<BaseResponse> HandleCreateAppointment(AppointmentManagementDto dto)
{
var validation = new CreateAppointmentValidator(_appointmentsMongoDbService,
_doctorRepository, _patientRepository);
var validationResult = await validation.ValidateAsync(dto);
if (!validationResult.IsValid)
{
var firstError = validationResult.Errors.FirstOrDefault();
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
var errorMessage = firstError.ErrorMessage;
return new BaseResponse
{
StatusCode = errorCode,
Message = errorMessage,
Data = null
};
}
var appointmentId = IdentifierGenerator.GenerateId(dto.DoctorId, dto.PatientId);
var criteria = new List<(string FieldName, string Value)>
{
("_id", appointmentId),
};
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
if(!appointments.Any())
{
var appointment = new Appointment();
appointment.SetId(appointmentId);
appointment.SetDoctorIid(dto.DoctorId.ToString());
appointment.SetPatientId(dto.PatientId.ToString());
appointment.AddAppointment(dto.Appointment);
await _appointmentsMongoDbService.AddAsync(appointment);
}
else
{
var appointment = appointments[0];
appointment.AddAppointment(dto.Appointment);
await _appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment);
}
return new BaseResponse()
{
StatusCode = HttpStatusCodes.Created,
Message = "Appointment successfully created.",
Data = null
};
}
public async Task<BaseResponse> HandleDeleteAppointment(AppointmentManagementDto dto)
{
var validation = new DeleteAppointmentValidator(_appointmentsMongoDbService,
_doctorRepository, _patientRepository);
var validationResult = await validation.ValidateAsync(dto);
if (!validationResult.IsValid)
{
var firstError = validationResult.Errors.FirstOrDefault();
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
var errorMessage = firstError.ErrorMessage;
return new BaseResponse
{
StatusCode = errorCode,
Message = errorMessage,
Data = null
};
}
var appointmentId = IdentifierGenerator.GenerateId(dto.DoctorId, dto.PatientId);
var criteria = new List<(string FieldName, string Value)>
{
("_id", appointmentId),
};
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
if(!appointments.Any())
{
return new BaseResponse()
{
StatusCode = HttpStatusCodes.NotFound,
Message = "Appointment not found in system.",
Data = null
};
}
var appointment = appointments[0];
appointment.RemoveAppointment(dto.Appointment);
await _appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment);
return new BaseResponse()
{
StatusCode = HttpStatusCodes.OK,
Message = "Appointment successfully removed.",
Data = null
};
}
}
@@ -0,0 +1,66 @@
using Application.Services.Database;
using Application.Services.Database.MongoDB;
using FluentValidation;
namespace Application.Endpoints.Appointments;
public class CreateAppointmentValidator : AbstractValidator<AppointmentManagementDto>
{
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
private readonly IDoctorRepository _doctorRepository;
private readonly IPatientRepository _patientRepository;
public CreateAppointmentValidator(IAppointmentsMongoDbService appointmentsMongoDbService,
IDoctorRepository doctorRepository, IPatientRepository patientRepository)
{
RuleFor(x => x.DoctorId)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsDoctorRegistered).WithMessage("Doctor is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.PatientId)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsPatientRegistered).WithMessage("Patient is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.Appointment)
.Must(IsAppointmentValidFormat).WithMessage("Appointment is not valid")
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
RuleFor(x => x)
.MustAsync(IsAppointmentUnique).WithMessage("Appointment already in system.")
.WithErrorCode(HttpStatusCodes.Conflict.ToString());
_appointmentsMongoDbService = appointmentsMongoDbService;
_doctorRepository = doctorRepository;
_patientRepository = patientRepository;
}
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
{
var doctor = await _doctorRepository.GetByIdAsync(id);
return doctor != null;
}
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
{
var patient = await _patientRepository.GetByIdAsync(id);
return patient != null;
}
private bool IsAppointmentValidFormat(DateTime appointment)
{
if (appointment == default(DateTime))
return false;
if (appointment.Date < DateTime.UtcNow.Date)
return false;
return true;
}
private async Task<bool> IsAppointmentUnique(AppointmentManagementDto dto, CancellationToken cancellationToken)
{
return await _appointmentsMongoDbService.IsAppointmentUnique(dto);
}
}
@@ -0,0 +1,67 @@
using Application.Services.Database;
using Application.Services.Database.MongoDB;
using Core.Entities;
using FluentValidation;
namespace Application.Endpoints.Appointments;
public class DeleteAppointmentValidator : AbstractValidator<AppointmentManagementDto>
{
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
private readonly IDoctorRepository _doctorRepository;
private readonly IPatientRepository _patientRepository;
public DeleteAppointmentValidator(IAppointmentsMongoDbService appointmentsMongoDbService,
IDoctorRepository doctorRepository, IPatientRepository patientRepository)
{
RuleFor(x => x.DoctorId)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsDoctorRegistered).WithMessage("Doctor is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.PatientId)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsPatientRegistered).WithMessage("Patient is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.Appointment)
.Must(IsAppointmentValidFormat).WithMessage("Appointment is not valid")
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
RuleFor(x => x)
.MustAsync(DoesAppointmentExists).WithMessage("Appointment not found in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
_appointmentsMongoDbService = appointmentsMongoDbService;
_doctorRepository = doctorRepository;
_patientRepository = patientRepository;
}
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
{
var doctor = await _doctorRepository.GetByIdAsync(id);
return doctor != null;
}
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
{
var patient = await _patientRepository.GetByIdAsync(id);
return patient != null;
}
private bool IsAppointmentValidFormat(DateTime appointment)
{
if (appointment == default(DateTime))
return false;
if (appointment.Date < DateTime.UtcNow.Date)
return false;
return true;
}
private async Task<bool> DoesAppointmentExists(AppointmentManagementDto dto, CancellationToken cancellationToken)
{
return await _appointmentsMongoDbService.DoesAppointmentExists(dto);
}
}
@@ -47,7 +47,7 @@ public class ChatHandler
};
}
var chatId = ChatIdentifier.GenerateChatId(sendMessageDto.Sender, sendMessageDto.Receiver);
var chatId = IdentifierGenerator.GenerateId(sendMessageDto.Sender, sendMessageDto.Receiver);
var criteria = new List<(string, string)>();
criteria.Add(("_id", chatId));
@@ -109,7 +109,7 @@ public class ChatHandler
};
}
var chatId = ChatIdentifier.GenerateChatId(getConversationDto.IdUser1, getConversationDto.IdUser2);
var chatId = IdentifierGenerator.GenerateId(getConversationDto.IdUser1, getConversationDto.IdUser2);
var criteria = new List<(string, string)>();
criteria.Add(("_id", chatId));
@@ -13,7 +13,7 @@ public class DoctorProfileValidation : AbstractValidator<DoctorProfileUpdateDto>
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsDoctorRegistered).WithMessage("Doctor is registered in system")
.MustAsync(IsDoctorRegistered).WithMessage("Doctor is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.Email)
@@ -40,7 +40,7 @@ public class DoctorProfileValidation : AbstractValidator<DoctorProfileUpdateDto>
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
{
var doctor = await _doctorRepository.GetByIdAsync(id);
return doctor == null;
return doctor != null;
}
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
@@ -1,8 +1,8 @@
namespace Application.Endpoints.Chats;
namespace Application.Endpoints;
public class ChatIdentifier
public class IdentifierGenerator
{
public static string GenerateChatId(Guid id1, Guid id2)
public static string GenerateId(Guid id1, Guid id2)
{
// Convert GUIDs to strings
string strId1 = id1.ToString();
@@ -31,7 +31,7 @@ public class MedicalHistoryFileManagementHandler
return new BaseResponse
{
StatusCode = HttpStatusCodes.NoContent,
StatusCode = HttpStatusCodes.NotFound,
Message = "Medical histories not found",
Data = null
};
@@ -13,7 +13,7 @@ public class PatientProfileValidation : AbstractValidator<PatientProfileDto>
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
.MustAsync(IsPatientRegistered).WithMessage("Patient is registered in system")
.MustAsync(IsPatientRegistered).WithMessage("Patient is not registered in system")
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
RuleFor(x => x.Email)
@@ -35,8 +35,8 @@ public class PatientProfileValidation : AbstractValidator<PatientProfileDto>
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
{
var doctor = await _patientRepository.GetByIdAsync(id);
return doctor == null;
var patient = await _patientRepository.GetByIdAsync(id);
return patient != null;
}
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
@@ -0,0 +1,23 @@
using Application.Endpoints.Appointments;
using MongoDB.Driver;
namespace Application.Services.Database.MongoDB;
public interface IAppointmentsMongoDbService
{
IMongoCollection<T> GetCollection<T>();
Task<List<T>> FindAsync<T>(List<(string FieldName, string Value)> criteria);
Task AddAsync<T>(T document);
Task ModifyAsync<T>(string keyField, string keyValue, T document);
Task DeleteAsync<T>(string keyField, string keyValue);
Task DeleteByIdAsync<T>(string id);
public Task<bool> IsAppointmentUnique(AppointmentManagementDto dto);
public Task<bool> DoesAppointmentExists(AppointmentManagementDto dto);
}
@@ -13,4 +13,6 @@ public interface IChatMongoDbService
Task ModifyAsync<T>(string keyField, string keyValue, T document);
Task DeleteAsync<T>(string keyField, string keyValue);
Task DeleteByIdAsync<T>(string id);
}
@@ -14,4 +14,6 @@ public interface IMedicalHistoryMongoDbService
Task ModifyAsync<T>(string keyField, string keyValue, T document);
Task DeleteAsync<T>(string keyField, string keyValue);
Task DeleteByIdAsync<T>(string id);
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Application")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+116405bd75830f3dec1c68562965bc78967039d5")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8663a186a056b0dfbfeebf9ae16be42b40101093")]
[assembly: System.Reflection.AssemblyProductAttribute("Application")]
[assembly: System.Reflection.AssemblyTitleAttribute("Application")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
2c0d3af716a6d40ccc6e2610395f654ee8489b15d024a3e4172c975777258df5
80601916b304e5754240a2dc14d4162100bc8fba5aed89bf6da00753d5c3920c
@@ -1 +1 @@
a14527b9f0436826149b6114fc93ca0d3615f169c5065e509d90189e6d49d7bf
23c9f8ecc5e36ec26454d9182eac70caff389e981316327bbd7443ce0fba8796
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/48eb2adcbd149cd66c77ba558f492179d2bf29be/*"}}
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/8663a186a056b0dfbfeebf9ae16be42b40101093/*"}}
+30
View File
@@ -0,0 +1,30 @@
namespace Core.Entities;
public class Appointment
{
public Appointment()
{
AppointmentsList = new List<DateTime>();
}
public string Id { get; private set; }
public string PatientId { get; private set; }
public string DoctorId { get; private set; }
public List<DateTime> AppointmentsList { get; private set; }
public void SetId(string id) { Id = id; }
public void SetPatientId(string patientId) { PatientId = patientId; }
public void SetDoctorIid(string doctorId) { DoctorId = doctorId; }
public void AddAppointment(DateTime appointmentDate)
{
DateTime utcAppointmentDate = new DateTime(appointmentDate.Year, appointmentDate.Month, appointmentDate.Day, 0, 0, 0, DateTimeKind.Utc);
AppointmentsList.Add(utcAppointmentDate);
}
public void RemoveAppointment(DateTime appointmentDate)
{
DateTime utcAppointmentDate = new DateTime(appointmentDate.Year, appointmentDate.Month, appointmentDate.Day, 0, 0, 0, DateTimeKind.Utc);
AppointmentsList.Remove(utcAppointmentDate);
}
}
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Core")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+116405bd75830f3dec1c68562965bc78967039d5")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8663a186a056b0dfbfeebf9ae16be42b40101093")]
[assembly: System.Reflection.AssemblyProductAttribute("Core")]
[assembly: System.Reflection.AssemblyTitleAttribute("Core")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
2b55ffa63c3c28b8380b15c20fdfc361e74063c09bcdfe546bd072959418bb1d
64c3fddc13943090bd8e18623615579ccefdab8583782b4c5a641fec31fea4c9
@@ -1 +1 @@
6236e3f912b0532e598b72e522cff0eefd892ca01f330905ca686a017c34f569
191029eab79e7925db94e77981abb39d1ba794fbe54c7d8989ebbb72ab0bc2dc
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/48eb2adcbd149cd66c77ba558f492179d2bf29be/*"}}
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/8663a186a056b0dfbfeebf9ae16be42b40101093/*"}}
Binary file not shown.
Binary file not shown.
+12 -5
View File
@@ -49,21 +49,28 @@ public static class DependencyInjection
return new ChatMongoDbService(connectionString, databaseName, collectionName);
});
services.AddSingleton<IAppointmentsMongoDbService>(serviceProvider =>
{
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var connectionString = configuration.GetConnectionString("MongoDBConnection");
var databaseName = configuration["HealthcareManagerDatabase:Name"];
var collectionName = configuration["HealthcareManagerDatabase:AppointmentsCollectionName"];
return new AppointmentsMongoDbService(connectionString, databaseName, collectionName);
});
// Other Services
services.AddScoped<IHashingAlgorithms, HashingAlgorithms>();
services.AddSingleton<IJwtService, JwtService>(serviceProvider =>
{
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
return new JwtService(configuration);
});
// services.AddScoped<IEmailService, EmailService>();
return services;
}
private static string ExtractMongoDbDatabaseName(string connectionString)
{
var connectionStringBuilder = new MongoUrlBuilder(connectionString);
return connectionStringBuilder.DatabaseName;
}
}
@@ -18,7 +18,7 @@ public class JwtService : IJwtService
_secretKey = configuration["Jwt:SecretKey"];
_issuer = configuration["Jwt:Issuer"];
_audience = configuration["Jwt:Audience"];
_expiryMinutes = double.Parse(configuration["Jwt:ExpiryMinutes"]);
_expiryMinutes = double.Parse(configuration["Jwt:ExpirationTime"]);
}
public string GenerateJwtToken(string email)
@@ -0,0 +1,59 @@
using Application.Endpoints.Appointments;
using Application.Services.Database.MongoDB;
using Core.Entities;
namespace Infrastructure.Services.MongoDB;
public class AppointmentsMongoDbService : MongoDbService, IAppointmentsMongoDbService
{
public AppointmentsMongoDbService(string connectionString, string databaseName, string collectionName)
: base(connectionString, databaseName, collectionName)
{
}
public async Task<bool> IsAppointmentUnique(AppointmentManagementDto dto)
{
var appointment = dto.Appointment.ToUniversalTime();
var criteria = new List<(string FieldName, string Value)>
{
("DoctorId", dto.DoctorId.ToString()),
("PatientId", dto.PatientId.ToString())
};
var appointments = await FindAsync<Appointment>(criteria);
foreach (var app in appointments)
{
if (app.AppointmentsList.Any(a => a.Date == appointment.Date))
{
return false;
}
}
return true;
}
public async Task<bool> DoesAppointmentExists(AppointmentManagementDto dto)
{
var appointment = dto.Appointment.ToUniversalTime();
var criteria = new List<(string FieldName, string Value)>
{
("DoctorId", dto.DoctorId.ToString()),
("PatientId", dto.PatientId.ToString())
};
var appointments = await FindAsync<Appointment>(criteria);
foreach (var app in appointments)
{
if (app.AppointmentsList.Any(a => a.Date == appointment.Date))
{
return true;
}
}
return false;
}
}
@@ -70,5 +70,12 @@ namespace Infrastructure.Services.MongoDB
var filter = Builders<T>.Filter.Eq(keyField, keyValue);
await collection.DeleteOneAsync(filter);
}
public async Task DeleteByIdAsync<T>(string id)
{
var collection = _database.GetDatabase(_databaseName).GetCollection<T>(_collectionName);
var filter = Builders<T>.Filter.Eq("_id", id);
await collection.DeleteOneAsync(filter);
}
}
}
Binary file not shown.
Binary file not shown.
@@ -16,8 +16,10 @@
"Microsoft.Extensions.Configuration": "8.0.0",
"Microsoft.Extensions.Configuration.Json": "8.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0",
"Microsoft.IdentityModel.Tokens": "7.5.1",
"MongoDB.Driver": "2.24.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "8.0.2"
"Npgsql.EntityFrameworkCore.PostgreSQL": "8.0.2",
"System.IdentityModel.Tokens.Jwt": "7.5.1"
},
"runtime": {
"Infrastructure.dll": {}
@@ -560,6 +562,47 @@
}
}
},
"Microsoft.IdentityModel.Abstractions/7.5.1": {
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.Logging/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.IdentityModel.Tokens/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "7.5.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"Microsoft.NETCore.Platforms/5.0.0": {},
"Microsoft.Win32.Registry/5.0.0": {
"dependencies": {
@@ -763,6 +806,18 @@
}
}
},
"System.IdentityModel.Tokens.Jwt/7.5.1": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "7.5.1",
"Microsoft.IdentityModel.Tokens": "7.5.1"
},
"runtime": {
"lib/net8.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "7.5.1.0",
"fileVersion": "7.5.1.50405"
}
}
},
"System.IO.Pipelines/6.0.3": {
"runtime": {
"lib/net6.0/System.IO.Pipelines.dll": {
@@ -1069,6 +1124,34 @@
"path": "microsoft.extensions.primitives/8.0.0",
"hashPath": "microsoft.extensions.primitives.8.0.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PT16ZFbPIiMsYv07oy3zOjqUOJ7xutGBkJTOX0+IbNyU6+O6X7aIxjq9EaSSRLWbekRgamgtmfg8Xjw6A6Ua9g==",
"path": "microsoft.identitymodel.abstractions/7.5.1",
"hashPath": "microsoft.identitymodel.abstractions.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-93CGSa8RPdZU8zfvA3nf9NGKUqEnQrE12VzYlMqKh72ddhzusosqLNEUgH/YhFWBLRFOnY1RCgHMV7pR+sAx2w==",
"path": "microsoft.identitymodel.jsonwebtokens/7.5.1",
"hashPath": "microsoft.identitymodel.jsonwebtokens.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PnpAQX20BAiDIPYmWUyQSlEaWD8BLXzHpiDGTCT568Cs0ReOeyzNe401LzCeiv6ilug/KefVeV1CeqtCHTo8dw==",
"path": "microsoft.identitymodel.logging/7.5.1",
"hashPath": "microsoft.identitymodel.logging.7.5.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Q3DKpyFViP84IUlTFKH/zIkswIrmSh2Vd/eFDo4wlOHy4DYxoweZEEw4kDEiKt9VCX6o7SddK3HK2xDYyFpexA==",
"path": "microsoft.identitymodel.tokens/7.5.1",
"hashPath": "microsoft.identitymodel.tokens.7.5.1.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
@@ -1209,6 +1292,13 @@
"path": "system.composition.typedparts/6.0.0",
"hashPath": "system.composition.typedparts.6.0.0.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/7.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UUw+E0R73lZLlXgneYIJQxNs1kfbcxjVzw64JQyiwjqCd4HMpAbjn+xRo86QZT84uHq8/MkqvfH82tgjgPzpuw==",
"path": "system.identitymodel.tokens.jwt/7.5.1",
"hashPath": "system.identitymodel.tokens.jwt.7.5.1.nupkg.sha512"
},
"System.IO.Pipelines/6.0.3": {
"type": "package",
"serviceable": true,
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Infrastructure")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+116405bd75830f3dec1c68562965bc78967039d5")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8663a186a056b0dfbfeebf9ae16be42b40101093")]
[assembly: System.Reflection.AssemblyProductAttribute("Infrastructure")]
[assembly: System.Reflection.AssemblyTitleAttribute("Infrastructure")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
73cfa8a3fe505da7a9d840f72821132ea5cd333c5d680c5413ad6c2d32eb0aa9
90add3a549a5ad86ae4df2628a148c5a9756bdaa56fd8988b963942aa2b42329
@@ -1 +1 @@
0fc8c2fdc4b952d96dcf80928d47de35d2afdbcca7797ecd9fa91d54ef6cedf9
f7db5be1a68464cc50c7ccee2ec8ca8c6b9870991fcbe7daa2045fdfe78ab58e
@@ -1 +1 @@
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/48eb2adcbd149cd66c77ba558f492179d2bf29be/*"}}
{"documents":{"C:\\Users\\Andrei Cerbu\\Documents\\FACULTATE\\CC-FinalProj\\*":"https://raw.githubusercontent.com/andrei-mihnea-cerbu/CC-FinalProj/8663a186a056b0dfbfeebf9ae16be42b40101093/*"}}