Unverified Commit ead3c9e3 authored by Almouhannad Hafez's avatar Almouhannad Hafez Committed by GitHub

Merge pull request #4 from Almouhannad/B_Refactoring-domain

B refactoring domain
parents 5d8df969 fe7a2b72
using API.Options.Database; using API.Options.Database;
using Domain.Repositories.Base;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Persistence.Context; using Persistence.Context;
using Persistence.Repositories.Base;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
...@@ -30,6 +32,11 @@ builder.Services.AddDbContext<ClinicsDbContext>( ...@@ -30,6 +32,11 @@ builder.Services.AddDbContext<ClinicsDbContext>(
// Add services to the container. // Add services to the container.
#region Link repositories
// AddTransient: Created on demand, every time they are requested, not shared across requests or components.
builder.Services.AddTransient(typeof(IRepository<>), typeof(Repositroy<>));
#endregion
#region Link controllers with presentation layer #region Link controllers with presentation layer
var presentationAssembly = typeof(Presentation.AssemblyReference).Assembly; var presentationAssembly = typeof(Presentation.AssemblyReference).Assembly;
builder.Services.AddControllers() builder.Services.AddControllers()
......
using Domain.Entities.People.Patients.Relations.PatientDiseases; using Domain.Entities.People.Patients.Relations.PatientDiseases;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Medicals.Diseases; namespace Domain.Entities.Medicals.Diseases;
public sealed class Disease(int id) : Entity(id) public sealed class Disease : Entity
{ {
#region Private ctor
private Disease(int id) : base(id) { }
private Disease(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
#region Navigations #region Navigations
public ICollection<PatientDisease> Patients { get; set; } = []; #region Patients
private readonly List<PatientDisease> _patients = [];
public IReadOnlyCollection<PatientDisease> Patients => _patients;
#endregion
#endregion
#endregion
#region Methods
#region Static factory
public static Disease Create(string name)
{
if (name is null)
throw new InvalidValuesDomainException<Disease>();
return new Disease(0, name);
}
#endregion #endregion
#endregion #endregion
......
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.Medicals.Hospitals; namespace Domain.Entities.Medicals.Hospitals;
public sealed class Hospital(int id) : Entity(id) public sealed class Hospital : Entity
{ {
#region Private ctor
private Hospital(int id) : base(id) { }
private Hospital(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
#endregion #endregion
#region Methods
#region Static factory
public static Hospital Create(string name)
{
if (name is null)
throw new InvalidValuesDomainException<Hospital>();
return new Hospital(0, name);
}
#endregion
#endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.Medicals.MedicalImages; namespace Domain.Entities.Medicals.MedicalImages;
public sealed class MedicalImage(int id) : Entity(id) public sealed class MedicalImage : Entity
{ {
#region Private ctor
private MedicalImage(int id) : base(id) { }
private MedicalImage(int id, string name, string? description = null) : base(id)
{
Name = name;
Description = description;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
...@@ -11,4 +22,17 @@ public sealed class MedicalImage(int id) : Entity(id) ...@@ -11,4 +22,17 @@ public sealed class MedicalImage(int id) : Entity(id)
public string? Description { get; set; } public string? Description { get; set; }
#endregion #endregion
#region Methods
#region Static factory
public static MedicalImage Create(string name, string? description = null)
{
if (name is null)
throw new InvalidValuesDomainException<MedicalImage>();
return new MedicalImage(0, name, description);
}
#endregion
#endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.Medicals.MedicalTests; namespace Domain.Entities.Medicals.MedicalTests;
public sealed class MedicalTest(int id) : Entity(id) public sealed class MedicalTest : Entity
{ {
#region Private ctor
private MedicalTest(int id) : base(id) { }
private MedicalTest(int id, string name, string? description = null) : base(id)
{
Name = name;
Description = description;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
...@@ -11,4 +22,17 @@ public sealed class MedicalTest(int id) : Entity(id) ...@@ -11,4 +22,17 @@ public sealed class MedicalTest(int id) : Entity(id)
public string? Description { get; set; } public string? Description { get; set; }
#endregion #endregion
#region Methods
#region Static factory
public static MedicalTest Create(string name, string description)
{
if (name is null)
throw new InvalidValuesDomainException<MedicalTest>();
return new MedicalTest(0, name, description);
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.Medicines.MedicineFormValues; using Domain.Entities.Medicals.Medicines.MedicineFormValues;
using Domain.Entities.People.Patients.Relations.PatientMedicines; using Domain.Entities.People.Patients.Relations.PatientMedicines;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Medicals.Medicines; namespace Domain.Entities.Medicals.Medicines;
// TODO: Convert Dosage to value object // TODO: Convert Dosage to value object
public sealed class Medicine(int id) : Entity(id) public sealed class Medicine : Entity
{ {
#region Private ctor
private Medicine(int id) : base(id) { }
private Medicine(int id, MedicineForm medicineForm, int amount, string name, decimal dosage) : base(id)
{
MedicineForm = medicineForm;
Amount = amount;
Name = name;
Dosage = dosage;
}
#endregion
#region Properties #region Properties
public MedicineForm MedicineForm { get; set; } = null!; public MedicineForm MedicineForm { get; set; } = null!;
public int Amount { get; set; }
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
public decimal Dosage { get; set; } public decimal Dosage { get; set; }
#region Navigations #region Navigations
public ICollection<PatientMedicine> Patients { get; set; } = []; #region Patients
private readonly List<PatientMedicine> _patients = [];
public IReadOnlyCollection<PatientMedicine> Patients => _patients;
#endregion
#endregion
#endregion
#region Methods
#region Static factory
public static Medicine Create(string form, int amount, string name, decimal dosage)
{
if (form is null || name is null || amount < 0 || dosage < 0)
throw new InvalidValuesDomainException<Medicine>();
#region Check form
MedicineForm selectedMedicineForm;
MedicineForm tablet = MedicineForms.Tablet;
MedicineForm syrup = MedicineForms.Syrup;
if (form == tablet.Name)
selectedMedicineForm = tablet;
else if (form == syrup.Name)
selectedMedicineForm = syrup;
else throw new InvalidValuesDomainException<MedicineForm>();
#endregion
return new Medicine(0, selectedMedicineForm, amount, name, dosage);
}
#endregion #endregion
#endregion #endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.Medicals.Medicines.MedicineFormValues; namespace Domain.Entities.Medicals.Medicines.MedicineFormValues;
public sealed class MedicineForm(int id) : Entity(id) public sealed class MedicineForm : Entity
{ {
#region Private ctor
private MedicineForm(int id) : base(id) { }
private MedicineForm(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
#endregion #endregion
#region Methods
#region Static factory
public static MedicineForm Create(string name, int? id)
{
if (name is null)
throw new InvalidValuesDomainException<MedicineForm>();
if (id is not null)
{
if (id < 0)
throw new InvalidValuesDomainException<MedicineForm>();
return new MedicineForm(id.Value, name);
}
return new MedicineForm(0, name);
}
#endregion
#endregion
} }
...@@ -4,9 +4,9 @@ public static class MedicineForms ...@@ -4,9 +4,9 @@ public static class MedicineForms
{ {
#region Constant id values #region Constant id values
public static int Tablet => 1; public static MedicineForm Tablet => MedicineForm.Create("حبوب", 1);
public static int Syrup => 2; public static MedicineForm Syrup => MedicineForm.Create("شراب", 2);
#endregion #endregion
} }
using Domain.Entities.People.Doctors.Shared; using Domain.Entities.People.Doctors.Shared;
using Domain.Entities.People.Doctors.Shared.Constants.DoctorStatusValues; using Domain.Entities.People.Doctors.Shared.Constants.DoctorStatusValues;
using Domain.Entities.People.Shared; using Domain.Entities.People.Shared;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Doctors; namespace Domain.Entities.People.Doctors;
public sealed class Doctor(int id) : Entity(id) public sealed class Doctor : Entity
{ {
#region Private ctor
private Doctor(int id) : base(id)
{
}
private Doctor(int id, PersonalInfo personalInfo) : base(id)
{
PersonalInfo = personalInfo;
Status = DoctorStatuses.Available;
}
#endregion
#region Properties #region Properties
public PersonalInfo PersonalInfo { get; set; } = null!; public PersonalInfo PersonalInfo { get; set; } = null!;
...@@ -15,8 +28,59 @@ public sealed class Doctor(int id) : Entity(id) ...@@ -15,8 +28,59 @@ public sealed class Doctor(int id) : Entity(id)
#region Navigations #region Navigations
public ICollection<DoctorPhone> Phones { get; set; } = []; #region Phones
private readonly List<DoctorPhone> _phones = [];
public IReadOnlyCollection<DoctorPhone> Phones => _phones;
#endregion
#endregion
#endregion
#region Methods
#region Static factory
public static Doctor Create(string firstName, string middleName, string lastName)
{
PersonalInfo personalInfo;
try
{
personalInfo = PersonalInfo.Create(firstName, middleName, lastName);
}
catch
{
throw;
}
return new Doctor(0, personalInfo);
}
#endregion
#region Add phone
public void AddPhone(string phone, string? number = null)
{
DoctorPhone doctorPhone;
try
{
doctorPhone = DoctorPhone.Create(phone, number);
}
catch
{
throw;
}
_phones.Add(doctorPhone);
}
#endregion
#region Change status
public void ChangeStatusTo(DoctorStatus status)
{
if (status == DoctorStatuses.Available || status == DoctorStatuses.Busy || status == DoctorStatuses.Working)
Status = status;
throw new InvalidValuesDomainException<DoctorStatus>();
}
#endregion #endregion
#endregion #endregion
......
using Domain.Primitives;
namespace Domain.Entities.People.Doctors.Shared.Constants.DoctorStatusValues;
public sealed class DoctorStatus(int id) : Entity(id)
{
#region Properties
public string Name { get; set; } = null!;
#endregion
}
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.People.Doctors.Shared; namespace Domain.Entities.People.Doctors.Shared;
// TODO: Convert phone property to a value object // TODO: Convert phone property to a value object
public sealed class DoctorPhone(int id) : Entity(id) public sealed class DoctorPhone : Entity
{ {
#region Private ctor
private DoctorPhone(int id) : base(id) { }
private DoctorPhone(int id, string phone, string? name = null) : base(id)
{
Phone = phone;
Name = name;
}
#endregion
#region Properties #region Properties
public string? Name { get; set; } public string? Name { get; set; }
...@@ -12,4 +23,19 @@ public sealed class DoctorPhone(int id) : Entity(id) ...@@ -12,4 +23,19 @@ public sealed class DoctorPhone(int id) : Entity(id)
public string Phone { get; set; } = null!; public string Phone { get; set; } = null!;
#endregion #endregion
#region Methods
#region Static factory
public static DoctorPhone Create(string phone, string? name)
{
if (phone is null)
throw new InvalidValuesDomainException<DoctorPhone>();
return new DoctorPhone(0, phone, name);
}
#endregion
#endregion
} }
using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.People.Doctors.Shared.Constants.DoctorStatusValues;
public sealed class DoctorStatus : Entity
{
#region Private ctor
private DoctorStatus(int id) : base(id)
{
}
private DoctorStatus(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties
public string Name { get; set; } = null!;
#endregion
#region Methods
#region Static factory
public static DoctorStatus Create(string name, int? id)
{
if (name is null)
throw new InvalidValuesDomainException<DoctorStatus>();
if (id is not null)
{
if (id < 0)
throw new InvalidValuesDomainException<DoctorStatus>();
return new DoctorStatus(id.Value, name);
}
return new DoctorStatus(0, name);
}
#endregion
#endregion
}
...@@ -4,11 +4,11 @@ public static class DoctorStatuses ...@@ -4,11 +4,11 @@ public static class DoctorStatuses
{ {
#region Constant id values #region Constant id values
public static int Available => 1; public static DoctorStatus Available => DoctorStatus.Create("متاح", 1);
public static int Working => 2; public static DoctorStatus Working => DoctorStatus.Create("لديه مريض", 1);
public static int Busy => 3; public static DoctorStatus Busy => DoctorStatus.Create("مشغول", 1);
#endregion #endregion
} }
using Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers; using Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers;
using Domain.Entities.People.Employees.Shared; using Domain.Entities.People.Employees.Shared;
using Domain.Entities.People.FamilyMembers;
using Domain.Entities.People.Patients; using Domain.Entities.People.Patients;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Employees; namespace Domain.Entities.People.Employees;
public sealed class Employee(int id) : Entity(id) public sealed class Employee : Entity
{ {
#region Private ctor
private Employee(int id) : base(id)
{
}
private Employee(int id,
Patient patient, string serialNumber, string centerStatus,
bool isMarried = false, EmployeeAdditionalInfo? additionalInfo = null)
: base(id)
{
Patient = patient;
SerialNumber = serialNumber;
CenterStatus = centerStatus;
IsMarried = isMarried;
AdditionalInfo = additionalInfo;
}
#endregion
#region Properties #region Properties
public Patient Patient { get; set; } = null!; public Patient Patient { get; set; } = null!;
...@@ -17,16 +38,102 @@ public sealed class Employee(int id) : Entity(id) ...@@ -17,16 +38,102 @@ public sealed class Employee(int id) : Entity(id)
public string CenterStatus { get; set; } = null!; public string CenterStatus { get; set; } = null!;
public bool IsMarried { get; set; } = false; public bool IsMarried { get; set; }
#region Navigations #region Navigations
public ICollection<EmployeeFamilyMember> FamilyMembers { get; set; } = []; #region Family members
private readonly List<EmployeeFamilyMember> _familyMembers = [];
public IReadOnlyCollection<EmployeeFamilyMember> FamilyMembers => _familyMembers;
#endregion
#region Related employees
private readonly List<Employee> _relatedEmployees = [];
public IReadOnlyCollection<Employee> RelatedEmployees => _relatedEmployees;
private readonly List<Employee> _relatedTo = [];
public IReadOnlyCollection<Employee> RelatedTo => _relatedTo;
#endregion
#endregion
public ICollection<Employee> RelatedEmployees { get; set; } = []; #endregion
#region Methods
#region Static factory
public static Employee Create(
string firstName, string middleName, string lastName, DateOnly dateOfBirth, string gender,
string serialNumber, string centerStatus, bool isMarried = false,
DateOnly? startDate = null, string? academicQualification = null, string? workPhone = null, string? location = null,
string? specialization = null, string? jobStatus = null, string? imageUrl = null
)
{
#region Create patient
Patient patient;
try
{
patient = Patient.Create(firstName, middleName, lastName, dateOfBirth, gender);
}
catch
{
throw;
}
#endregion
#region Check employee's required details
if (serialNumber is null || centerStatus is null)
throw new InvalidValuesDomainException<Employee>();
#endregion
#region Create additional info
EmployeeAdditionalInfo additionalInfo;
try
{
additionalInfo = EmployeeAdditionalInfo.Create(startDate, academicQualification,
workPhone, location, specialization, jobStatus, imageUrl);
}
catch
{
throw;
}
#endregion
return new Employee(0, patient, serialNumber, centerStatus, isMarried, additionalInfo);
}
#endregion
public ICollection<Employee> RelatedTo { get; set; } = []; #region Add family member
public void AddFamilyMember(FamilyMember familyMember, string role)
{
EmployeeFamilyMember employeeFamilyMember;
try
{
employeeFamilyMember = EmployeeFamilyMember.Create(Id, familyMember.Id, role);
}
catch
{
throw;
}
_familyMembers.Add(employeeFamilyMember);
}
#endregion
#region Add related employee
public void AddRelatedEmployee(Employee employee)
{
_relatedEmployees.Add(employee);
}
#endregion #endregion
#endregion #endregion
......
using Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers.FamilyRoleValues; using Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers.FamilyRoleValues;
using Domain.Entities.People.FamilyMembers; using Domain.Entities.People.FamilyMembers;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers; namespace Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers;
public sealed class EmployeeFamilyMember(int id) : Entity(id) public sealed class EmployeeFamilyMember : Entity
{ {
#region Private ctor
private EmployeeFamilyMember(int id) : base(id)
{
}
private EmployeeFamilyMember(int id, int employeeId, int familyMemberId, FamilyRole role) : base(id)
{
EmployeeId = employeeId;
FamilyMemberId = familyMemberId;
Role = role;
}
#endregion
#region Properties #region Properties
#region Employee #region Employee
...@@ -29,4 +42,42 @@ public sealed class EmployeeFamilyMember(int id) : Entity(id) ...@@ -29,4 +42,42 @@ public sealed class EmployeeFamilyMember(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static EmployeeFamilyMember Create(int employeeId, int familyMemberId, string role)
{
if (employeeId <= 0 || familyMemberId <= 0 || role is null)
throw new InvalidValuesDomainException<EmployeeFamilyMember>();
#region Check role
FamilyRole? selectedRole;
FamilyRole husband = FamilyRoles.Husband;
FamilyRole wife = FamilyRoles.Wife;
FamilyRole son = FamilyRoles.Son;
FamilyRole daughter = FamilyRoles.Daughter;
if (role == husband.Name)
selectedRole = husband;
else if (role == wife.Name)
selectedRole = wife;
else if (role == son.Name)
selectedRole = son;
else if (role == daughter.Name)
selectedRole = daughter;
else selectedRole = null;
if (selectedRole is null)
throw new InvalidValuesDomainException<FamilyRole>();
#endregion
return new EmployeeFamilyMember(0, employeeId, familyMemberId, selectedRole);
}
#endregion
#endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers.FamilyRoleValues; namespace Domain.Entities.People.Employees.Relations.EmployeeFamilyMembers.FamilyRoleValues;
public sealed class FamilyRole(int id) : Entity(id) public sealed class FamilyRole : Entity
{ {
#region Private ctor
private FamilyRole(int id) : base(id)
{
}
private FamilyRole(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
#endregion #endregion
#region Methods
#region Static factory
public static FamilyRole Create(string name, int? id)
{
if (name is null)
throw new InvalidValuesDomainException<FamilyRole>();
if (id is not null)
{
if (id < 0)
throw new InvalidValuesDomainException<FamilyRole>();
return new FamilyRole(id.Value, name);
}
return new FamilyRole(0, name);
}
#endregion
#endregion
} }
...@@ -4,13 +4,13 @@ public static class FamilyRoles ...@@ -4,13 +4,13 @@ public static class FamilyRoles
{ {
#region Constant id values #region Constant id values
public static int Husband => 1; public static FamilyRole Husband => FamilyRole.Create("زوج", 1);
public static int Wife => 2; public static FamilyRole Wife => FamilyRole.Create("زوجة", 2);
public static int Son => 3; public static FamilyRole Son => FamilyRole.Create("ابن", 3);
public static int Daughter => 4; public static FamilyRole Daughter => FamilyRole.Create("ابنة", 4);
#endregion #endregion
} }
...@@ -3,8 +3,36 @@ ...@@ -3,8 +3,36 @@
namespace Domain.Entities.People.Employees.Shared; namespace Domain.Entities.People.Employees.Shared;
// TODO: Convert to a value object containig value objects // TODO: Convert to a value object containig value objects
public sealed class EmployeeAdditionalInfo(int id) : Entity(id) public sealed class EmployeeAdditionalInfo : Entity
{ {
#region Private ctor
private EmployeeAdditionalInfo(int id) : base(id)
{
}
private EmployeeAdditionalInfo(int id,
DateOnly? startDate,
string? academicQualification,
string? workPhone,
string? location,
string? specialization,
string? jobStatus,
string? imageUrl
)
: base(id)
{
StartDate = startDate;
AcademicQualification = academicQualification;
WorkPhone = workPhone;
Location = location;
Specialization = specialization;
JobStatus = jobStatus;
ImageUrl = imageUrl;
}
#endregion
#region Properties #region Properties
public DateOnly? StartDate { get; set; } public DateOnly? StartDate { get; set; }
...@@ -22,4 +50,22 @@ public sealed class EmployeeAdditionalInfo(int id) : Entity(id) ...@@ -22,4 +50,22 @@ public sealed class EmployeeAdditionalInfo(int id) : Entity(id)
public string? ImageUrl { get; set; } public string? ImageUrl { get; set; }
#endregion #endregion
#region Methods
#region Static factory
public static EmployeeAdditionalInfo Create(DateOnly? startDate,
string? academicQualification,
string? workPhone,
string? location,
string? specialization,
string? jobStatus,
string? imageUrl)
{
return new EmployeeAdditionalInfo(0,
startDate, academicQualification, workPhone, location, specialization, jobStatus, imageUrl);
}
#endregion
#endregion
} }
...@@ -3,11 +3,49 @@ using Domain.Primitives; ...@@ -3,11 +3,49 @@ using Domain.Primitives;
namespace Domain.Entities.People.FamilyMembers; namespace Domain.Entities.People.FamilyMembers;
public sealed class FamilyMember(int id) : Entity(id) public sealed class FamilyMember : Entity
{ {
#region Private ctor
private FamilyMember(int id) : base(id)
{
}
private FamilyMember(int id, Patient patient) : base(id)
{
Patient = patient;
}
#endregion
#region Properties #region Properties
public Patient Patient { get; set; } = null!; public Patient Patient { get; set; } = null!;
#endregion #endregion
#region Methods
#region Static factory
public static FamilyMember Create(string firstName, string middleName, string lastName,
DateOnly dateOfBirth,
string gender
)
{
#region Create patient
Patient patient;
try
{
patient = Patient.Create(firstName, middleName, lastName, dateOfBirth, gender);
}
catch
{
throw;
}
#endregion
return new FamilyMember(0, patient);
}
#endregion
#endregion
} }
using Domain.Entities.People.Patients.Relations.PatientDiseases; using Domain.Entities.Medicals.Diseases;
using Domain.Entities.Medicals.Medicines;
using Domain.Entities.People.Patients.Relations.PatientDiseases;
using Domain.Entities.People.Patients.Relations.PatientMedicines; using Domain.Entities.People.Patients.Relations.PatientMedicines;
using Domain.Entities.People.Shared; using Domain.Entities.People.Shared;
using Domain.Entities.People.Shared.GenderValues; using Domain.Entities.People.Shared.GenderValues;
using Domain.Entities.Visits; using Domain.Entities.Visits;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Patients; namespace Domain.Entities.People.Patients;
// TODO: Potential aggregate? // TODO: Potential aggregate?
public sealed class Patient(int id) : Entity(id) public sealed class Patient : Entity
{ {
#region Private ctor
private Patient(int id) : base(id) { }
private Patient(int id, PersonalInfo personalInfo, DateOnly dateOfBirth, Gender gender) : base(id)
{
PersonalInfo = personalInfo;
DateOfBirth = dateOfBirth;
Gender = gender;
}
#endregion
#region Properties #region Properties
public PersonalInfo PersonalInfo { get; set; } = null!; public PersonalInfo PersonalInfo { get; private set; } = null!;
public DateOnly DateOfBirth { get; private set; }
public DateOnly DateOfBirth { get; set; } public int Age
{
get
{
var today = DateOnly.FromDateTime(DateTime.Today);
var age = today.Year - DateOfBirth.Year;
if (today.Month < DateOfBirth.Month || (today.Month == DateOfBirth.Month && today.Day < DateOfBirth.Day))
{
age--;
}
return age;
}
}
public Gender Gender { get; set; } = null!; public Gender Gender { get; private set; } = null!;
#region Navigations #region Navigations
public ICollection<PatientDisease> Diseases { get; set; } = []; #region Diseases
private readonly List<PatientDisease> _diseases = [];
public IReadOnlyCollection<PatientDisease> Diseases => _diseases;
#endregion
#region Medicines
private readonly List<PatientMedicine> _medicines = [];
public IReadOnlyCollection<PatientMedicine> Medicines => _medicines;
#endregion
#region Visits
private readonly List<Visit> _visits = [];
public IReadOnlyCollection<Visit> Visits => _visits;
#endregion
#endregion
#endregion
#region Methods
#region Static factory
public static Patient Create(string firstName, string middleName, string lastName,
DateOnly dateOfBirth,
string gender
)
{
#region Personal info
PersonalInfo? personalInfo;
try
{
personalInfo = PersonalInfo.Create(firstName, middleName, lastName);
}
catch
{
throw;
}
#endregion
#region Gender
if (gender is null)
throw new InvalidValuesDomainException<Gender>();
Gender? selectedGender;
Gender male = Genders.Male;
Gender female = Genders.Female;
public ICollection<PatientMedicine> Medicines { get; set; } = []; if (gender == male.Name)
selectedGender = male;
else if (gender == female.Name)
selectedGender = female;
else selectedGender = null;
if (selectedGender is null)
throw new InvalidValuesDomainException<Gender>();
#endregion
return new Patient(0, personalInfo, dateOfBirth, selectedGender);
}
#endregion
#region Add medicine
public void AddMedicine(Medicine medicine, int number)
{
PatientMedicine entry;
try
{
entry = PatientMedicine.Create(Id, medicine.Id, number);
}
catch
{
throw;
}
_medicines.Add(entry);
}
#endregion
public ICollection<Visit> Visits { get; set; } = []; #region Add disease
public void AddDisease (Disease disease)
{
PatientDisease entry;
try
{
entry = PatientDisease.Create(Id, disease.Id);
}
catch
{
throw;
}
_diseases.Add(entry);
}
#endregion #endregion
#endregion #endregion
......
using Domain.Entities.Medicals.Diseases; using Domain.Entities.Medicals.Diseases;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Patients.Relations.PatientDiseases; namespace Domain.Entities.People.Patients.Relations.PatientDiseases;
public sealed class PatientDisease(int id) : Entity(id) public sealed class PatientDisease : Entity
{ {
#region Private ctor
private PatientDisease(int id) : base(id)
{
}
private PatientDisease(int id, int patientId, int diseaseId) : base(id)
{
PatientId = patientId;
DiseaseId = diseaseId;
}
#endregion
#region Properties #region Properties
...@@ -27,4 +39,17 @@ public sealed class PatientDisease(int id) : Entity(id) ...@@ -27,4 +39,17 @@ public sealed class PatientDisease(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static PatientDisease Create(int patientId, int diseaseId)
{
if (patientId <= 0 || diseaseId <= 0)
throw new InvalidValuesDomainException<PatientDisease>();
return new PatientDisease(0, patientId, diseaseId);
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.Medicines; using Domain.Entities.Medicals.Medicines;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.People.Patients.Relations.PatientMedicines; namespace Domain.Entities.People.Patients.Relations.PatientMedicines;
public sealed class PatientMedicine(int id) : Entity(id) public sealed class PatientMedicine : Entity
{ {
#region Private ctor
private PatientMedicine(int id) : base(id)
{
}
private PatientMedicine(int id, int patientId, int medicineId, int number) : base(id)
{
PatientId = patientId;
MedicineId = medicineId;
Number = number;
}
#endregion
#region Properties #region Properties
#region Patient #region Patient
...@@ -28,5 +44,18 @@ public sealed class PatientMedicine(int id) : Entity(id) ...@@ -28,5 +44,18 @@ public sealed class PatientMedicine(int id) : Entity(id)
#endregion #endregion
#endregion
#region Methods
#region Static factory
public static PatientMedicine Create(int patientId, int medicineId, int number)
{
if (patientId <= 0 || medicineId <= 0 || number <= 0)
throw new InvalidValuesDomainException<PatientMedicine>();
return new PatientMedicine(0, patientId, medicineId, number);
}
#endregion
#endregion #endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.People.Shared.GenderValues; namespace Domain.Entities.People.Shared.GenderValues;
// TODO: Convert to a value object // TODO: Convert to a value object
public sealed class Gender(int id) : Entity(id) public sealed class Gender : Entity
{ {
#region Private ctor
private Gender(int id) : base(id) { }
private Gender(int id, string name) : base(id)
{
Name = name;
}
#endregion
#region Properties #region Properties
public string Name { get; set; } = null!; public string Name { get; private set; } = null!;
#endregion
#region Methods
#region Static factory
public static Gender Create(string name, int? id)
{
if (name is null)
throw new InvalidValuesDomainException<Gender>();
if (id is not null)
{
if (id < 0)
throw new InvalidValuesDomainException<Gender>();
return new Gender(id.Value, name);
}
return new Gender(0, name);
}
#endregion
#endregion #endregion
} }
...@@ -4,9 +4,9 @@ public static class Genders ...@@ -4,9 +4,9 @@ public static class Genders
{ {
#region Constant id values #region Constant id values
public static int Male => 1; public static Gender Male => Gender.Create("ذكر", 1);
public static int Female => 2; public static Gender Female => Gender.Create("أنثى", 2);
#endregion #endregion
} }
using Domain.Primitives; using Domain.Exceptions.InvalidValue;
using Domain.Primitives;
namespace Domain.Entities.People.Shared; namespace Domain.Entities.People.Shared;
// TODO: Convert props to value objects // TODO: Convert props to value objects
public sealed class PersonalInfo(int id) : Entity(id) public sealed class PersonalInfo : Entity
{ {
#region Private ctor
private PersonalInfo(int id) : base(id) { }
private PersonalInfo(int id, string firstName, string middleName, string lastName) : base(id)
{
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
}
#endregion
#region Properties #region Properties
public string FirstName { get; set; } = null!; public string FirstName { get; private set; } = null!;
public string MiddleName { get; private set; } = null!;
public string MiddleName { get; set; } = null!; public string LastName { get; private set; } = null!;
public string LastName { get; set; } = null!; public string FullName
{
get
{
return $"{FirstName} {MiddleName} {LastName}";
}
}
#endregion #endregion
#region Methods
#region Static factory
public static PersonalInfo Create(string firstName, string middleName, string lastName)
{
if (firstName is null || middleName is null || lastName is null)
throw new InvalidValuesDomainException<PersonalInfo>();
return new PersonalInfo(0, firstName, middleName, lastName);
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.MedicalImages; using Domain.Entities.Medicals.MedicalImages;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Visits.Relations.VisitMedicalImages; namespace Domain.Entities.Visits.Relations.VisitMedicalImages;
// TODO: Convert result to a value object // TODO: Convert result to a value object
public sealed class VisitMedicalImage(int id) : Entity(id) public sealed class VisitMedicalImage : Entity
{ {
#region Private ctor
private VisitMedicalImage(int id) : base(id) { }
private VisitMedicalImage(int id, int visitId, int medicalImageId) : base(id)
{
VisitId = visitId;
MedicalImageId = medicalImageId;
Result = null;
}
#endregion
#region Properties #region Properties
#region Visit #region Visit
...@@ -29,4 +44,28 @@ public sealed class VisitMedicalImage(int id) : Entity(id) ...@@ -29,4 +44,28 @@ public sealed class VisitMedicalImage(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static VisitMedicalImage Create(int visitId, int medicalImageId)
{
if (visitId <= 0 || medicalImageId <= 0)
throw new InvalidValuesDomainException<VisitMedicalImage>();
return new VisitMedicalImage(0, visitId, medicalImageId);
}
#endregion
#region Add result
public void AddResult(string result)
{
if (result is null)
throw new InvalidValuesDomainException<VisitMedicalImage>();
Result = result;
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.MedicalTests; using Domain.Entities.Medicals.MedicalTests;
using Domain.Entities.Visits.Relations.VisitMedicalImages;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Visits.Relations.VisitMedicalTests; namespace Domain.Entities.Visits.Relations.VisitMedicalTests;
// TODO: Convert result to a value object // TODO: Convert result to a value object
public sealed class VisitMedicalTest(int id) : Entity(id) public sealed class VisitMedicalTest : Entity
{ {
#region Private ctor
private VisitMedicalTest(int id) : base(id) { }
private VisitMedicalTest(int id, int visitId, int medicalTestId) : base(id)
{
VisitId = visitId;
MedicalTestId = medicalTestId;
Result = null;
}
#endregion
#region Properties #region Properties
#region Visit #region Visit
...@@ -29,4 +45,28 @@ public sealed class VisitMedicalTest(int id) : Entity(id) ...@@ -29,4 +45,28 @@ public sealed class VisitMedicalTest(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static VisitMedicalTest Create(int visitId, int medicalTestId)
{
if (visitId <= 0 || medicalTestId <= 0)
throw new InvalidValuesDomainException<VisitMedicalTest>();
return new VisitMedicalTest(0, visitId, medicalTestId);
}
#endregion
#region Add result
public void AddResult(string result)
{
if (result is null)
throw new InvalidValuesDomainException<VisitMedicalTest>();
Result = result;
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.Medicines; using Domain.Entities.Medicals.Medicines;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Visits.Relations.VisitMedicines; namespace Domain.Entities.Visits.Relations.VisitMedicines;
public sealed class VisitMedicine(int id) : Entity(id) public sealed class VisitMedicine : Entity
{ {
#region Private ctor
private VisitMedicine(int id) : base(id) { }
private VisitMedicine(int id, int visitId, int medicineId, int number) : base(id)
{
VisitId = visitId;
MedicineId = medicineId;
Number = number;
}
#endregion
#region Properties #region Properties
#region Visit #region Visit
...@@ -28,4 +42,18 @@ public sealed class VisitMedicine(int id) : Entity(id) ...@@ -28,4 +42,18 @@ public sealed class VisitMedicine(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static VisitMedicine Create(int visitId, int medicineId, int number)
{
if (visitId <= 0 || medicineId <= 0 || number <= 0)
throw new InvalidValuesDomainException<VisitMedicine>();
return new VisitMedicine(0, visitId, medicineId, number);
}
#endregion
#endregion
} }
using Domain.Entities.Medicals.Hospitals; using Domain.Entities.Medicals.Hospitals;
using Domain.Entities.Medicals.MedicalImages;
using Domain.Entities.Medicals.MedicalTests;
using Domain.Entities.Medicals.Medicines;
using Domain.Entities.People.Doctors; using Domain.Entities.People.Doctors;
using Domain.Entities.People.Patients; using Domain.Entities.People.Patients;
using Domain.Entities.Visits.Relations.VisitMedicalImages; using Domain.Entities.Visits.Relations.VisitMedicalImages;
using Domain.Entities.Visits.Relations.VisitMedicalTests; using Domain.Entities.Visits.Relations.VisitMedicalTests;
using Domain.Entities.Visits.Relations.VisitMedicines; using Domain.Entities.Visits.Relations.VisitMedicines;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.Visits; namespace Domain.Entities.Visits;
public sealed class Visit(int id) : Entity(id) public sealed class Visit : Entity
{ {
#region Private ctor
private Visit(int id) : base(id) { }
private Visit(int id, int patientId, int doctorId, DateOnly date, string diagnosis) : base(id)
{
PatientId = patientId;
DoctorId = doctorId;
Date = date;
Diagnosis = diagnosis;
HospitalId = null;
}
#endregion
#region Properties #region Properties
#region Patient
public int PatientId { get; set; }
public Patient Patient { get; set; } = null!; public Patient Patient { get; set; } = null!;
#endregion
#region Doctor
public int DoctorId { get; set; }
public Doctor Doctor { get; set; } = null!; public Doctor Doctor { get; set; } = null!;
public Hospital? Hospital { get; set; } #endregion
#region Additional
public DateOnly Date { get; set; } public DateOnly Date { get; set; }
public string Diagnosis { get; set; } = null!; public string Diagnosis { get; set; } = null!;
#region Hospital
public int? HospitalId { get; set; }
public Hospital? Hospital { get; set; }
#endregion
#endregion
#region Navigations #region Navigations
public ICollection<VisitMedicalImage> MedicalImages { get; set; } = []; #region Medical images
public ICollection<VisitMedicalTest> MedicalTests { get; set; } = []; private readonly List<VisitMedicalImage> _medicalImages = [];
public ICollection<VisitMedicine> Medicines { get; set; } = []; public IReadOnlyCollection<VisitMedicalImage> MedicalImages => _medicalImages;
#endregion
#region Medical tests
private readonly List<VisitMedicalTest> _medicalTests = [];
public IReadOnlyCollection<VisitMedicalTest> MedicalTests => _medicalTests;
#endregion
#region Medicines
private readonly List<VisitMedicine> _medicines = [];
public IReadOnlyCollection<VisitMedicine> Medicines => _medicines;
#endregion
#endregion
#endregion
#region Methods
#region Static factory
public static Visit Create(int patientId, int doctorId, DateOnly date, string diagnosis)
{
if (patientId <= 0 || doctorId <= 0 || diagnosis is null)
throw new InvalidValuesDomainException<Visit>();
return new Visit(0, patientId, doctorId, date, diagnosis);
}
#endregion
#region Add medical image
public void AddMedicalImage(MedicalImage medicalImage)
{
VisitMedicalImage entry;
try
{
entry = VisitMedicalImage.Create(Id, medicalImage.Id);
}
catch
{
throw;
}
_medicalImages.Add(entry);
}
#endregion
#region Add medical test
public void AddMedicalTest(MedicalTest medicalTest)
{
VisitMedicalTest entry;
try
{
entry = VisitMedicalTest.Create(Id, medicalTest.Id);
}
catch
{
throw;
}
_medicalTests.Add(entry);
}
#endregion
#region Add medicine
public void AddMedicine (Medicine medicine, int number)
{
VisitMedicine entry;
try
{
entry = VisitMedicine.Create(Id, medicine.Id, number);
}
catch
{
throw;
}
_medicines.Add(entry);
}
#endregion
#region Add hospital
public void AddHospital(Hospital hospital)
{
if (hospital is null)
throw new InvalidValuesDomainException<Visit>();
Hospital = hospital;
HospitalId = hospital.Id;
}
#endregion #endregion
#endregion #endregion
......
using Domain.Entities.People.Doctors; using Domain.Entities.People.Doctors;
using Domain.Entities.People.Patients; using Domain.Entities.People.Patients;
using Domain.Exceptions.InvalidValue;
using Domain.Primitives; using Domain.Primitives;
namespace Domain.Entities.WaitingList; namespace Domain.Entities.WaitingList;
public sealed class WaitingListRecord(int id) : Entity(id) public sealed class WaitingListRecord : Entity
{ {
#region Private ctor
private WaitingListRecord(int id) : base(id) { }
private WaitingListRecord(int id, int patientId) : base(id)
{
PatientId = patientId;
IsServed = false;
}
#endregion
#region Properties #region Properties
#region Patient #region Patient
...@@ -29,4 +41,28 @@ public sealed class WaitingListRecord(int id) : Entity(id) ...@@ -29,4 +41,28 @@ public sealed class WaitingListRecord(int id) : Entity(id)
#endregion #endregion
#endregion #endregion
#region Methods
#region Static factory
public static WaitingListRecord Create(int patientId)
{
if (patientId <= 0)
throw new InvalidValuesDomainException<WaitingListRecord>();
return new WaitingListRecord(0, patientId);
}
#endregion
#region Link to doctor
public void LinkToDoctor(int doctorId)
{
if (doctorId <= 0)
throw new InvalidValuesDomainException<WaitingListRecord>();
DoctorId = doctorId;
}
#endregion
#endregion
} }
namespace Domain.Exceptions.Base;
public abstract class DomainException : Exception
{
protected DomainException(string message) : base(message)
{
}
}
using Domain.Exceptions.Base;
using Domain.Primitives;
namespace Domain.Exceptions.InvalidValue;
public class InvalidValuesDomainException<TEntity> : DomainException
where TEntity : Entity
{
public InvalidValuesDomainException(string message = $"Values entered for entity {nameof(TEntity)} are invalid")
: base(message)
{
}
}
...@@ -10,6 +10,8 @@ internal class PatientConfiguration : IEntityTypeConfiguration<Patient> ...@@ -10,6 +10,8 @@ internal class PatientConfiguration : IEntityTypeConfiguration<Patient>
{ {
builder.ToTable(nameof(Patient)); builder.ToTable(nameof(Patient));
builder.Ignore(patient => patient.Age);
builder.HasOne(patient => patient.PersonalInfo) builder.HasOne(patient => patient.PersonalInfo)
.WithOne() .WithOne()
.HasForeignKey<Patient>("PersonalInfoId") .HasForeignKey<Patient>("PersonalInfoId")
...@@ -21,6 +23,7 @@ internal class PatientConfiguration : IEntityTypeConfiguration<Patient> ...@@ -21,6 +23,7 @@ internal class PatientConfiguration : IEntityTypeConfiguration<Patient>
builder.HasMany(patient => patient.Visits) builder.HasMany(patient => patient.Visits)
.WithOne(visit => visit.Patient) .WithOne(visit => visit.Patient)
.HasForeignKey(visit => visit.PatientId)
.OnDelete(DeleteBehavior.NoAction); .OnDelete(DeleteBehavior.NoAction);
} }
} }
\ No newline at end of file
...@@ -10,8 +10,12 @@ internal class PersonalInfoConfiguration : IEntityTypeConfiguration<PersonalInfo ...@@ -10,8 +10,12 @@ internal class PersonalInfoConfiguration : IEntityTypeConfiguration<PersonalInfo
{ {
builder.ToTable(nameof(PersonalInfo)); builder.ToTable(nameof(PersonalInfo));
builder.Ignore(personalInfo => personalInfo.FullName);
builder.Property(personalInfo => personalInfo.FirstName).HasMaxLength(50); builder.Property(personalInfo => personalInfo.FirstName).HasMaxLength(50);
builder.Property(personalInfo => personalInfo.LastName).HasMaxLength(50); builder.Property(personalInfo => personalInfo.LastName).HasMaxLength(50);
builder.Property(personalInfo => personalInfo.MiddleName).HasMaxLength(50); builder.Property(personalInfo => personalInfo.MiddleName).HasMaxLength(50);
} }
} }
...@@ -14,10 +14,12 @@ internal class VisitConfiguration : IEntityTypeConfiguration<Visit> ...@@ -14,10 +14,12 @@ internal class VisitConfiguration : IEntityTypeConfiguration<Visit>
builder.HasOne(visit => visit.Doctor) builder.HasOne(visit => visit.Doctor)
.WithMany() .WithMany()
.HasForeignKey(visit => visit.DoctorId)
.OnDelete(DeleteBehavior.NoAction); .OnDelete(DeleteBehavior.NoAction);
builder.HasOne(visit => visit.Hospital) builder.HasOne(visit => visit.Hospital)
.WithMany() .WithMany()
.HasForeignKey(visit => visit.HospitalId)
.OnDelete(DeleteBehavior.NoAction); .OnDelete(DeleteBehavior.NoAction);
} }
} }
\ No newline at end of file
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Persistence.Migrations
{
/// <inheritdoc />
public partial class Add_Amount_To_Medicine : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Amount",
table: "Medicine",
type: "int",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Amount",
table: "Medicine");
}
}
}
...@@ -110,6 +110,9 @@ namespace Persistence.Migrations ...@@ -110,6 +110,9 @@ namespace Persistence.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Amount")
.HasColumnType("int");
b.Property<decimal>("Dosage") b.Property<decimal>("Dosage")
.HasColumnType("numeric(9, 3)"); .HasColumnType("numeric(9, 3)");
......
...@@ -29,7 +29,9 @@ public class Repositroy<TEntity> : IRepository<TEntity> where TEntity : Entity ...@@ -29,7 +29,9 @@ public class Repositroy<TEntity> : IRepository<TEntity> where TEntity : Entity
public async Task<TEntity> CreateAsync(TEntity entity) public async Task<TEntity> CreateAsync(TEntity entity)
{ {
return await _context.Set<TEntity>().FirstAsync(e => e.Id == entity.Id); var query = await _context.Set<TEntity>().AddAsync(entity);
await _context.SaveChangesAsync();
return query.Entity;
} }
#endregion #endregion
...@@ -43,7 +45,7 @@ public class Repositroy<TEntity> : IRepository<TEntity> where TEntity : Entity ...@@ -43,7 +45,7 @@ public class Repositroy<TEntity> : IRepository<TEntity> where TEntity : Entity
public async Task<ICollection<TEntity>> GetAllAsync() public async Task<ICollection<TEntity>> GetAllAsync()
{ {
return await _context.Set<TEntity>().ToListAsync<TEntity>(); return await _context.Set<TEntity>().ToListAsync();
} }
#endregion #endregion
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment