diff --git a/.gitignore b/.gitignore index 8e08cec..bcd8b69 100644 --- a/.gitignore +++ b/.gitignore @@ -262,7 +262,6 @@ ServiceFabricBackup/ *.rptproj.bak # SQL Server files -*.mdf *.ldf *.ndf @@ -415,4 +414,6 @@ FodyWeavers.xsd # Built Visual Studio Code Extensions *.vsix -test_results.txt \ No newline at end of file +test_results.txt +/Library/Tests/Instrumentation/Library.mdf +/run_tests.sh diff --git a/DataLayerTests/DataLayerTests.cs b/DataLayerTests/DataLayerTests.cs new file mode 100644 index 0000000..8197e25 --- /dev/null +++ b/DataLayerTests/DataLayerTests.cs @@ -0,0 +1,114 @@ +using DataLayer.API; +using Microsoft.Data.SqlClient; + +namespace DataLayerTests +{ + [TestClass] + [DeploymentItem("MockDB.mdf")] // DB is copied to the deployment directory where the test is executed. + public class DataLayerTests + { + private static string connectionString; + + // private readonly IDataRepository _dataRepository = IDataRepository.NewInstance(IDataContext.NewInstance(connectionString)); + + private IDataRepository _dataRepository; + + + [ClassInitialize] + public static void ClassInitializeMethod(TestContext context) + { + string _DBRelativePath = @"MockDB.mdf"; + string _projectRootDir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName; + string _DBPath = Path.Combine(_projectRootDir, _DBRelativePath); + FileInfo _databaseFile = new FileInfo(_DBPath); + Assert.IsTrue(_databaseFile.Exists, $"{Environment.CurrentDirectory}"); + + connectionString = $@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={_DBPath};Integrated Security = True; Connect Timeout = 30;"; + } + + [TestInitialize] + public void TestInitialize() + { + IDataContext dataContext = IDataContext.NewInstance(connectionString); + _dataRepository = IDataRepository.NewInstance(dataContext); + } + + [TestMethod] + public void TestDatabaseConnection() + { + using (SqlConnection connection = new SqlConnection(connectionString)) + { + try + { + connection.Open(); + Assert.IsTrue(connection.State == System.Data.ConnectionState.Open, "Connection to the database failed."); + } + catch (Exception ex) + { + Assert.Fail($"Exception occurred while connecting to the database: {ex.Message}"); + } + } + } + + [TestMethod] + public async Task UserTests() + { + string userGuid = "cfaf2913-3677-4c56-a1cd-fa1647"; + + // Add a new user + string firstName = "John"; + string lastName = "Wick"; + string email = "johnwick@continental.com"; + double balance = 1000000; + string phoneNumber = "315-194-6020"; + await _dataRepository.AddUserAsync(userGuid, firstName, lastName, email, balance, phoneNumber); + + IUser retrivedUser = await _dataRepository.GetUserAsync(userGuid); + + // Assert that the user is correctly retrieved and the data is correct + Assert.IsNotNull(retrivedUser); + Assert.AreEqual(userGuid, retrivedUser.Guid); + Assert.AreEqual(firstName, retrivedUser.FirstName); + Assert.AreEqual(email, retrivedUser.Email); + Assert.AreEqual(balance, retrivedUser.Balance); + Assert.AreEqual(phoneNumber, retrivedUser.PhoneNumber); + + Assert.IsNotNull(await _dataRepository.GetAllUsersAsync()); + Assert.IsTrue(await _dataRepository.GetUsersCountAsync() > 0); + + string notExistingUserGuid = "afaf2913-1234-4c56-a1cd-fa1647"; + await Assert.ThrowsExceptionAsync(async () => await _dataRepository.GetUserAsync(notExistingUserGuid)); + + // John Wick moves to a new place to start a new life + string newFirstName = "Tom"; + string newLastName = "Hanks"; + string newEmail = "notjohnwick@continental.com"; + double newBalance = 9000000; + string newPhoneNumber = "1-951-239-0523"; + await _dataRepository.UpdateUserAsync(userGuid, newFirstName, newLastName, newEmail, newBalance, newPhoneNumber); + + // Retrieve the updated data of now not John Wick + IUser updatedUser = await _dataRepository.GetUserAsync(userGuid); + + // Assert that the the identity change was successful + Assert.IsNotNull(updatedUser); + Assert.AreEqual(newFirstName, updatedUser.FirstName); + Assert.AreEqual(newLastName, updatedUser.LastName); + Assert.AreEqual(newEmail, updatedUser.Email); + Assert.AreEqual(newBalance, updatedUser.Balance); + Assert.AreEqual(newPhoneNumber, updatedUser.PhoneNumber); + + await Assert.ThrowsExceptionAsync(async () => await _dataRepository.UpdateUserAsync(notExistingUserGuid, + "John", "Doe", "johndow@wp.pl", 666, "123321123")); + + // John Wick disappears from the system + await _dataRepository.DeleteUserAsync(userGuid); + + // Assert that an exception is thrown when trying to retrieve the deleted user + await Assert.ThrowsExceptionAsync(async () => await _dataRepository.GetUserAsync(userGuid)); + + // Assert that an exception is thrown when trying to delete the already deleted user + await Assert.ThrowsExceptionAsync(async () => await _dataRepository.DeleteUserAsync(userGuid)); + } + } +} diff --git a/DataLayerTests/DataLayerTests.csproj b/DataLayerTests/DataLayerTests.csproj new file mode 100644 index 0000000..62238c0 --- /dev/null +++ b/DataLayerTests/DataLayerTests.csproj @@ -0,0 +1,28 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + diff --git a/DataLayerTests/MockDB.mdf b/DataLayerTests/MockDB.mdf new file mode 100644 index 0000000..1eb9862 Binary files /dev/null and b/DataLayerTests/MockDB.mdf differ diff --git a/Library.sln b/Library.sln index e82fbbc..80bacbf 100644 --- a/Library.sln +++ b/Library.sln @@ -3,13 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataLayer", "Library\DataLayer\DataLayer.csproj", "{37F35CAD-0E16-44DE-B1EC-B8806B87AF27}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Library\Tests\Tests.csproj", "{E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataLayer", "Library\DataLayer\DataLayer.csproj", "{37F35CAD-0E16-44DE-B1EC-B8806B87AF27}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{B858A003-F5DD-4F95-99D9-5A7560A0B8CF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogicLayer", "Library\LogicLayer\LogicLayer.csproj", "{34D82E95-A0C6-4C12-8BB0-6836280E2491}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Presentation", "Library\Presentation\Presentation.csproj", "{C69FD601-389B-4CD1-A1FF-899261179F05}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceLayerTests", "Library\ServiceLayerTests\ServiceLayerTests.csproj", "{0AB5386A-930A-4A24-A6E5-ED00D8E5355E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataLayerTests", "DataLayerTests\DataLayerTests.csproj", "{66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Service", "Library\Service\Service.csproj", "{AD1B47F1-3FB2-41A7-9C6C-41F294FF835E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PresentationLayerTests", "Library\PresentationLayerTests\PresentationLayerTests.csproj", "{D30BB53A-B80E-45CF-B3F1-B8C39A8C849D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,22 +27,39 @@ Global {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Debug|Any CPU.Build.0 = Debug|Any CPU {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Release|Any CPU.ActiveCfg = Release|Any CPU {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Release|Any CPU.Build.0 = Release|Any CPU - {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Release|Any CPU.Build.0 = Release|Any CPU - {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Release|Any CPU.Build.0 = Release|Any CPU + {C69FD601-389B-4CD1-A1FF-899261179F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C69FD601-389B-4CD1-A1FF-899261179F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C69FD601-389B-4CD1-A1FF-899261179F05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C69FD601-389B-4CD1-A1FF-899261179F05}.Release|Any CPU.Build.0 = Release|Any CPU + {0AB5386A-930A-4A24-A6E5-ED00D8E5355E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AB5386A-930A-4A24-A6E5-ED00D8E5355E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AB5386A-930A-4A24-A6E5-ED00D8E5355E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AB5386A-930A-4A24-A6E5-ED00D8E5355E}.Release|Any CPU.Build.0 = Release|Any CPU + {66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1}.Release|Any CPU.Build.0 = Release|Any CPU + {AD1B47F1-3FB2-41A7-9C6C-41F294FF835E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD1B47F1-3FB2-41A7-9C6C-41F294FF835E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD1B47F1-3FB2-41A7-9C6C-41F294FF835E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD1B47F1-3FB2-41A7-9C6C-41F294FF835E}.Release|Any CPU.Build.0 = Release|Any CPU + {D30BB53A-B80E-45CF-B3F1-B8C39A8C849D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D30BB53A-B80E-45CF-B3F1-B8C39A8C849D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D30BB53A-B80E-45CF-B3F1-B8C39A8C849D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D30BB53A-B80E-45CF-B3F1-B8C39A8C849D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {37F35CAD-0E16-44DE-B1EC-B8806B87AF27} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + {C69FD601-389B-4CD1-A1FF-899261179F05} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + {0AB5386A-930A-4A24-A6E5-ED00D8E5355E} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + {66C9D42F-4CBD-474F-B4FB-5FDFAB58C2A1} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + {AD1B47F1-3FB2-41A7-9C6C-41F294FF835E} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + {D30BB53A-B80E-45CF-B3F1-B8C39A8C849D} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B8DC2F37-8FC7-433C-BA78-56CAE077B47B} EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {34D82E95-A0C6-4C12-8BB0-6836280E2491} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} - EndGlobalSection EndGlobal diff --git a/Library/DataLayer/API/IDataContext.cs b/Library/DataLayer/API/IDataContext.cs index 29f8bcd..7a616f7 100644 --- a/Library/DataLayer/API/IDataContext.cs +++ b/Library/DataLayer/API/IDataContext.cs @@ -1,13 +1,64 @@ +using DataLayer.Implementations; + namespace DataLayer.API { public interface IDataContext { - public List Users { get; set; } + static IDataContext NewInstance(string? connectionString = null) { + return new DataContext(connectionString); + } + + #region User CRUD + + Task AddUserAsync(IUser user); + Task GetUserAsync(string guid); + Task UpdateUserAsync(IUser user); + Task DeleteUserAsync(string guid); + Task> GetAllUsersAsync(); + Task GetUsersCountAsync(); + + #endregion User CRUD + + #region Product CRUD + + Task AddProductAsync(IBook product); + Task GetProductAsync(string guid); + Task UpdateProductAsync(IBook product); + Task DeleteProductAsync(string guid); + Task> GetAllProductsAsync(); + Task GetProductsCountAsync(); + + #endregion + + #region State CRUD + + Task AddStateAsync(IState state); + Task GetStateAsync(string guid); + Task UpdateStateAsync(IState state); + Task DeleteStateAsync(string guid); + Task> GetAllStatesAsync(); + Task GetStatesCountAsync(); + + #endregion + + #region Event CRUD + + Task AddEventAsync(IEvent even); + Task GetEventAsync(string guid); + Task UpdateEventAsync(IEvent even); + Task DeleteEventAsync(string guid); + Task> GetAllEventsAsync(); + Task GetEventsCountAsync(); + + #endregion - public List Products { get; set; } + #region Helpers - public List Events { get; set; } + Task CheckIfUserExists(string guid); + Task CheckIfProductExists(string guid); + Task CheckIfStateExists(string guid); + Task CheckIfEventExists(string guid, string type); - public List States { get; set; } + #endregion } } \ No newline at end of file diff --git a/Library/DataLayer/API/IDataRepository.cs b/Library/DataLayer/API/IDataRepository.cs index c7f3724..4c442a6 100644 --- a/Library/DataLayer/API/IDataRepository.cs +++ b/Library/DataLayer/API/IDataRepository.cs @@ -4,42 +4,63 @@ namespace DataLayer.API { public interface IDataRepository { + static IDataRepository NewInstance(IDataContext? dataContext = null) + { + return new DataRepository(dataContext ?? DataContext.NewInstance()); + } + public void Seed(IDataFiller dataSeeder); - #region User - void AddUser(IUser user); - IUser GetUser(string guid); - List GetAllUsers(); - void RemoveUser(string guid); - bool DoesUserExist(string guid); - void UpdateUser(IUser updateUser); - #endregion + static IDataRepository CreateDatabase(IDataContext? dataContext = null) + { + return DataRepository.NewInstance(dataContext ?? new DataContext()); + } + + #region User CRUD + + Task AddUserAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber); + Task GetUserAsync(string guid); + Task UpdateUserAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber); + Task DeleteUserAsync(string guid); + Task> GetAllUsersAsync(); + Task GetUsersCountAsync(); + + #endregion User CRUD + + + #region Product CRUD - #region Product - void AddProduct(IProduct product); - IProduct GetProduct(string guid); - List GetAllProducts(); - IProduct GetProductByState(string stateGuid); - bool DoesProductExist(string guid); + Task AddProductAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate); + Task GetProductAsync(string guid); + Task UpdateProductAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate); + Task DeleteProductAsync(string guid); + Task> GetAllProductsAsync(); + Task GetProductsCountAsync(); - void RemoveProduct(string guid); #endregion - #region Event - void AddEvent(IEvent @event); - IEvent GetEvent(string guid); - List GetAllEvents(); - List GetEventsByUser(string userGuid); - List GetEventsByProduct(string productGuid); - List GetEventsByState(string stateGuid); - void RemoveEvent(string guid); + + #region State CRUD + + Task AddStateAsync(string guid, string productGuid, int quantity); + Task GetStateAsync(string guid); + Task UpdateStateAsync(string guid, string productGuid, int quantity); + Task DeleteStateAsync(string guid); + Task> GetAllStatesAsync(); + Task GetStatesCountAsync(); + #endregion - #region State - void AddState(IState state); - IState GetState(string guid); - List GetAllStates(); - void RemoveState(string guid); + + #region Event CRUD + + Task AddEventAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type); + Task GetEventAsync(string guid); + Task UpdateEventAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type); + Task DeleteEventAsync(string guid); + Task> GetAllEventsAsync(); + Task GetEventsCountAsync(); + #endregion } } \ No newline at end of file diff --git a/Library/DataLayer/API/IEvent.cs b/Library/DataLayer/API/IEvent.cs index 4bc8a34..d434483 100644 --- a/Library/DataLayer/API/IEvent.cs +++ b/Library/DataLayer/API/IEvent.cs @@ -2,9 +2,10 @@ namespace DataLayer.API { public interface IEvent { - string Guid { get; } - IUser User { get; } - IState State { get; } - DateTime CreatedAt { get; } + string Guid { get; set; } + string UserGuid { get; set; } + string StateGuid { get; set; } + string Type { get; set; } + DateTime CreatedAt { get; set; } } } diff --git a/Library/DataLayer/API/IProduct.cs b/Library/DataLayer/API/IProduct.cs index 3e971ce..6b89f12 100644 --- a/Library/DataLayer/API/IProduct.cs +++ b/Library/DataLayer/API/IProduct.cs @@ -2,7 +2,7 @@ namespace DataLayer.API { public interface IProduct { - string Guid { get; } + string Guid { get; set; } string Name { get; set; } double Price { get; set; } } diff --git a/Library/DataLayer/API/IState.cs b/Library/DataLayer/API/IState.cs index eeecc5d..11fa999 100644 --- a/Library/DataLayer/API/IState.cs +++ b/Library/DataLayer/API/IState.cs @@ -2,9 +2,8 @@ namespace DataLayer.API { public interface IState { - IProduct Product { get; set; } + string Guid { get; set; } int Quantity { get; set; } - DateTime LastUpdatedDate { get; } - string Guid { get; } + string ProductGuid { get; set; } } } diff --git a/Library/DataLayer/API/IUser.cs b/Library/DataLayer/API/IUser.cs index 5df25fe..7591a48 100644 --- a/Library/DataLayer/API/IUser.cs +++ b/Library/DataLayer/API/IUser.cs @@ -3,14 +3,12 @@ namespace DataLayer.API public interface IUser { // guid, because is more commonly used in contexts of the Microsoft ecosystem - string Guid { get; } + string Guid { get; set; } string FirstName { get; set; } string LastName { get; set; } string Email { get; set; } double Balance { get; set; } // stick to E.164 standard? - int PhoneNumber { get; set; } - // string Role { get; set; } - Dictionary ProductsDic { get; set; } + string PhoneNumber { get; set; } } } \ No newline at end of file diff --git a/Library/DataLayer/App.config b/Library/DataLayer/App.config new file mode 100644 index 0000000..02f1a75 --- /dev/null +++ b/Library/DataLayer/App.config @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/Library/DataLayer/DataLayer.csproj b/Library/DataLayer/DataLayer.csproj index 152c270..e769ae5 100644 --- a/Library/DataLayer/DataLayer.csproj +++ b/Library/DataLayer/DataLayer.csproj @@ -1,12 +1,16 @@  - net8.0 + net6.0 enable enable README.md + + + + True @@ -14,4 +18,32 @@ + + + + + + + + MSLinqToSQLGenerator + LibraryDataClasses.designer.cs + + + + + + + + + + True + True + LibraryDataClasses.dbml + + + + + + + \ No newline at end of file diff --git a/Library/DataLayer/Database/Database.mdf b/Library/DataLayer/Database/Database.mdf new file mode 100644 index 0000000..a1e3b75 Binary files /dev/null and b/Library/DataLayer/Database/Database.mdf differ diff --git a/Library/DataLayer/Database/LibraryDataClasses.dbml b/Library/DataLayer/Database/LibraryDataClasses.dbml new file mode 100644 index 0000000..ff86c55 --- /dev/null +++ b/Library/DataLayer/Database/LibraryDataClasses.dbml @@ -0,0 +1,46 @@ + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + +
+
\ No newline at end of file diff --git a/Library/DataLayer/Database/LibraryDataClasses.dbml.layout b/Library/DataLayer/Database/LibraryDataClasses.dbml.layout new file mode 100644 index 0000000..21bb36e --- /dev/null +++ b/Library/DataLayer/Database/LibraryDataClasses.dbml.layout @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Library/DataLayer/Database/LibraryDataClasses.designer.cs b/Library/DataLayer/Database/LibraryDataClasses.designer.cs new file mode 100644 index 0000000..241284d --- /dev/null +++ b/Library/DataLayer/Database/LibraryDataClasses.designer.cs @@ -0,0 +1,995 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DataLayer.Database +{ + using System.Data.Linq; + using System.Data.Linq.Mapping; + using System.Data; + using System.Collections.Generic; + using System.Reflection; + using System.Linq; + using System.Linq.Expressions; + using System.ComponentModel; + using System; + + + [global::System.Data.Linq.Mapping.DatabaseAttribute(Name="Database")] + public partial class LibraryDataClassesDataContext : System.Data.Linq.DataContext + { + + private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource(); + + #region Extensibility Method Definitions + partial void OnCreated(); + partial void InsertUser(User instance); + partial void UpdateUser(User instance); + partial void DeleteUser(User instance); + partial void InsertState(State instance); + partial void UpdateState(State instance); + partial void DeleteState(State instance); + partial void InsertEvent(Event instance); + partial void UpdateEvent(Event instance); + partial void DeleteEvent(Event instance); + partial void InsertBook(Book instance); + partial void UpdateBook(Book instance); + partial void DeleteBook(Book instance); + #endregion + + public LibraryDataClassesDataContext(string connection) : + base(connection, mappingSource) + { + OnCreated(); + } + + public LibraryDataClassesDataContext(System.Data.IDbConnection connection) : + base(connection, mappingSource) + { + OnCreated(); + } + + public LibraryDataClassesDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) : + base(connection, mappingSource) + { + OnCreated(); + } + + public LibraryDataClassesDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) : + base(connection, mappingSource) + { + OnCreated(); + } + + public System.Data.Linq.Table User + { + get + { + return this.GetTable(); + } + } + + public System.Data.Linq.Table State + { + get + { + return this.GetTable(); + } + } + + public System.Data.Linq.Table Event + { + get + { + return this.GetTable(); + } + } + + public System.Data.Linq.Table Book + { + get + { + return this.GetTable(); + } + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Users")] + public partial class User : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _guid; + + private string _firstName; + + private string _lastName; + + private string _email; + + private double _balance; + + private string _phoneNumber; + + private EntitySet _Events; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnguidChanging(string value); + partial void OnguidChanged(); + partial void OnfirstNameChanging(string value); + partial void OnfirstNameChanged(); + partial void OnlastNameChanging(string value); + partial void OnlastNameChanged(); + partial void OnemailChanging(string value); + partial void OnemailChanged(); + partial void OnbalanceChanging(double value); + partial void OnbalanceChanged(); + partial void OnphoneNumberChanging(string value); + partial void OnphoneNumberChanged(); + #endregion + + public User() + { + this._Events = new EntitySet(new Action(this.attach_Events), new Action(this.detach_Events)); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_guid", DbType="VarChar(36) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] + public string guid + { + get + { + return this._guid; + } + set + { + if ((this._guid != value)) + { + this.OnguidChanging(value); + this.SendPropertyChanging(); + this._guid = value; + this.SendPropertyChanged("guid"); + this.OnguidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_firstName", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string firstName + { + get + { + return this._firstName; + } + set + { + if ((this._firstName != value)) + { + this.OnfirstNameChanging(value); + this.SendPropertyChanging(); + this._firstName = value; + this.SendPropertyChanged("firstName"); + this.OnfirstNameChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_lastName", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string lastName + { + get + { + return this._lastName; + } + set + { + if ((this._lastName != value)) + { + this.OnlastNameChanging(value); + this.SendPropertyChanging(); + this._lastName = value; + this.SendPropertyChanged("lastName"); + this.OnlastNameChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_email", DbType="NVarChar(255) NOT NULL", CanBeNull=false)] + public string email + { + get + { + return this._email; + } + set + { + if ((this._email != value)) + { + this.OnemailChanging(value); + this.SendPropertyChanging(); + this._email = value; + this.SendPropertyChanged("email"); + this.OnemailChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_balance", DbType="Float NOT NULL")] + public double balance + { + get + { + return this._balance; + } + set + { + if ((this._balance != value)) + { + this.OnbalanceChanging(value); + this.SendPropertyChanging(); + this._balance = value; + this.SendPropertyChanged("balance"); + this.OnbalanceChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_phoneNumber", DbType="NVarChar(15) NOT NULL", CanBeNull=false)] + public string phoneNumber + { + get + { + return this._phoneNumber; + } + set + { + if ((this._phoneNumber != value)) + { + this.OnphoneNumberChanging(value); + this.SendPropertyChanging(); + this._phoneNumber = value; + this.SendPropertyChanged("phoneNumber"); + this.OnphoneNumberChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="Users_Events", Storage="_Events", ThisKey="guid", OtherKey="userGuid")] + public EntitySet Event + { + get + { + return this._Events; + } + set + { + this._Events.Assign(value); + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void attach_Events(Event entity) + { + this.SendPropertyChanging(); + entity.User = this; + } + + private void detach_Events(Event entity) + { + this.SendPropertyChanging(); + entity.User = null; + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.States")] + public partial class State : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _guid; + + private string _productGuid; + + private int _quantity; + + private System.DateTime _LastUpdatedDate; + + private EntitySet _Events; + + private EntityRef _Books; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnguidChanging(string value); + partial void OnguidChanged(); + partial void OnproductGuidChanging(string value); + partial void OnproductGuidChanged(); + partial void OnquantityChanging(int value); + partial void OnquantityChanged(); + partial void OnLastUpdatedDateChanging(System.DateTime value); + partial void OnLastUpdatedDateChanged(); + #endregion + + public State() + { + this._Events = new EntitySet(new Action(this.attach_Events), new Action(this.detach_Events)); + this._Books = default(EntityRef); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_guid", DbType="VarChar(36) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] + public string guid + { + get + { + return this._guid; + } + set + { + if ((this._guid != value)) + { + if (this._Books.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnguidChanging(value); + this.SendPropertyChanging(); + this._guid = value; + this.SendPropertyChanged("guid"); + this.OnguidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_productGuid", DbType="VarChar(36) NOT NULL", CanBeNull=false)] + public string productGuid + { + get + { + return this._productGuid; + } + set + { + if ((this._productGuid != value)) + { + this.OnproductGuidChanging(value); + this.SendPropertyChanging(); + this._productGuid = value; + this.SendPropertyChanged("productGuid"); + this.OnproductGuidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_quantity", DbType="Int NOT NULL")] + public int quantity + { + get + { + return this._quantity; + } + set + { + if ((this._quantity != value)) + { + this.OnquantityChanging(value); + this.SendPropertyChanging(); + this._quantity = value; + this.SendPropertyChanged("quantity"); + this.OnquantityChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_LastUpdatedDate", DbType="Date NOT NULL")] + public System.DateTime LastUpdatedDate + { + get + { + return this._LastUpdatedDate; + } + set + { + if ((this._LastUpdatedDate != value)) + { + this.OnLastUpdatedDateChanging(value); + this.SendPropertyChanging(); + this._LastUpdatedDate = value; + this.SendPropertyChanged("LastUpdatedDate"); + this.OnLastUpdatedDateChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="States_Events", Storage="_Events", ThisKey="guid", OtherKey="stateGuid")] + public EntitySet Event + { + get + { + return this._Events; + } + set + { + this._Events.Assign(value); + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="Books_States", Storage="_Books", ThisKey="guid", OtherKey="guid", IsForeignKey=true)] + public Book Book + { + get + { + return this._Books.Entity; + } + set + { + Book previousValue = this._Books.Entity; + if (((previousValue != value) + || (this._Books.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._Books.Entity = null; + previousValue.State = null; + } + this._Books.Entity = value; + if ((value != null)) + { + value.State = this; + this._guid = value.guid; + } + else + { + this._guid = default(string); + } + this.SendPropertyChanged("Book"); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + private void attach_Events(Event entity) + { + this.SendPropertyChanging(); + entity.State = this; + } + + private void detach_Events(Event entity) + { + this.SendPropertyChanging(); + entity.State = null; + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Events")] + public partial class Event : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _guid; + + private string _userGuid; + + private string _stateGuid; + + private string _type; + + private System.DateTime _createdAt; + + private EntityRef _States; + + private EntityRef _Users; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnguidChanging(string value); + partial void OnguidChanged(); + partial void OnuserGuidChanging(string value); + partial void OnuserGuidChanged(); + partial void OnstateGuidChanging(string value); + partial void OnstateGuidChanged(); + partial void OntypeChanging(string value); + partial void OntypeChanged(); + partial void OncreatedAtChanging(System.DateTime value); + partial void OncreatedAtChanged(); + #endregion + + public Event() + { + this._States = default(EntityRef); + this._Users = default(EntityRef); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_guid", DbType="VarChar(36) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] + public string guid + { + get + { + return this._guid; + } + set + { + if ((this._guid != value)) + { + this.OnguidChanging(value); + this.SendPropertyChanging(); + this._guid = value; + this.SendPropertyChanged("guid"); + this.OnguidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_userGuid", DbType="VarChar(36) NOT NULL", CanBeNull=false)] + public string userGuid + { + get + { + return this._userGuid; + } + set + { + if ((this._userGuid != value)) + { + if (this._Users.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnuserGuidChanging(value); + this.SendPropertyChanging(); + this._userGuid = value; + this.SendPropertyChanged("userGuid"); + this.OnuserGuidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_stateGuid", DbType="VarChar(36) NOT NULL", CanBeNull=false)] + public string stateGuid + { + get + { + return this._stateGuid; + } + set + { + if ((this._stateGuid != value)) + { + if (this._States.HasLoadedOrAssignedValue) + { + throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException(); + } + this.OnstateGuidChanging(value); + this.SendPropertyChanging(); + this._stateGuid = value; + this.SendPropertyChanged("stateGuid"); + this.OnstateGuidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_type", DbType="NVarChar(50) NOT NULL", CanBeNull=false)] + public string type + { + get + { + return this._type; + } + set + { + if ((this._type != value)) + { + this.OntypeChanging(value); + this.SendPropertyChanging(); + this._type = value; + this.SendPropertyChanged("type"); + this.OntypeChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_createdAt", DbType="DateTime NOT NULL")] + public System.DateTime createdAt + { + get + { + return this._createdAt; + } + set + { + if ((this._createdAt != value)) + { + this.OncreatedAtChanging(value); + this.SendPropertyChanging(); + this._createdAt = value; + this.SendPropertyChanged("createdAt"); + this.OncreatedAtChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="States_Events", Storage="_States", ThisKey="stateGuid", OtherKey="guid", IsForeignKey=true)] + public State State + { + get + { + return this._States.Entity; + } + set + { + State previousValue = this._States.Entity; + if (((previousValue != value) + || (this._States.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._States.Entity = null; + previousValue.Event.Remove(this); + } + this._States.Entity = value; + if ((value != null)) + { + value.Event.Add(this); + this._stateGuid = value.guid; + } + else + { + this._stateGuid = default(string); + } + this.SendPropertyChanged("State"); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="Users_Events", Storage="_Users", ThisKey="userGuid", OtherKey="guid", IsForeignKey=true)] + public User User + { + get + { + return this._Users.Entity; + } + set + { + User previousValue = this._Users.Entity; + if (((previousValue != value) + || (this._Users.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._Users.Entity = null; + previousValue.Event.Remove(this); + } + this._Users.Entity = value; + if ((value != null)) + { + value.Event.Add(this); + this._userGuid = value.guid; + } + else + { + this._userGuid = default(string); + } + this.SendPropertyChanged("User"); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Books")] + public partial class Book : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _guid; + + private string _name; + + private double _price; + + private string _author; + + private string _publisher; + + private int _pages; + + private System.DateTime _publicationDate; + + private EntityRef _States; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnguidChanging(string value); + partial void OnguidChanged(); + partial void OnnameChanging(string value); + partial void OnnameChanged(); + partial void OnpriceChanging(double value); + partial void OnpriceChanged(); + partial void OnauthorChanging(string value); + partial void OnauthorChanged(); + partial void OnpublisherChanging(string value); + partial void OnpublisherChanged(); + partial void OnpagesChanging(int value); + partial void OnpagesChanged(); + partial void OnpublicationDateChanging(System.DateTime value); + partial void OnpublicationDateChanged(); + #endregion + + public Book() + { + this._States = default(EntityRef); + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_guid", DbType="VarChar(36) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] + public string guid + { + get + { + return this._guid; + } + set + { + if ((this._guid != value)) + { + this.OnguidChanging(value); + this.SendPropertyChanging(); + this._guid = value; + this.SendPropertyChanged("guid"); + this.OnguidChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_name", DbType="VarChar(50) NOT NULL", CanBeNull=false)] + public string name + { + get + { + return this._name; + } + set + { + if ((this._name != value)) + { + this.OnnameChanging(value); + this.SendPropertyChanging(); + this._name = value; + this.SendPropertyChanged("name"); + this.OnnameChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_price", DbType="Float NOT NULL")] + public double price + { + get + { + return this._price; + } + set + { + if ((this._price != value)) + { + this.OnpriceChanging(value); + this.SendPropertyChanging(); + this._price = value; + this.SendPropertyChanged("price"); + this.OnpriceChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_author", DbType="VarChar(50) NOT NULL", CanBeNull=false)] + public string author + { + get + { + return this._author; + } + set + { + if ((this._author != value)) + { + this.OnauthorChanging(value); + this.SendPropertyChanging(); + this._author = value; + this.SendPropertyChanged("author"); + this.OnauthorChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_publisher", DbType="VarChar(50) NOT NULL", CanBeNull=false)] + public string publisher + { + get + { + return this._publisher; + } + set + { + if ((this._publisher != value)) + { + this.OnpublisherChanging(value); + this.SendPropertyChanging(); + this._publisher = value; + this.SendPropertyChanged("publisher"); + this.OnpublisherChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_pages", DbType="Int NOT NULL")] + public int pages + { + get + { + return this._pages; + } + set + { + if ((this._pages != value)) + { + this.OnpagesChanging(value); + this.SendPropertyChanging(); + this._pages = value; + this.SendPropertyChanged("pages"); + this.OnpagesChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_publicationDate", DbType="DateTime NOT NULL")] + public System.DateTime publicationDate + { + get + { + return this._publicationDate; + } + set + { + if ((this._publicationDate != value)) + { + this.OnpublicationDateChanging(value); + this.SendPropertyChanging(); + this._publicationDate = value; + this.SendPropertyChanged("publicationDate"); + this.OnpublicationDateChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.AssociationAttribute(Name="Books_States", Storage="_States", ThisKey="guid", OtherKey="guid", IsUnique=true, IsForeignKey=false)] + public State State + { + get + { + return this._States.Entity; + } + set + { + State previousValue = this._States.Entity; + if (((previousValue != value) + || (this._States.HasLoadedOrAssignedValue == false))) + { + this.SendPropertyChanging(); + if ((previousValue != null)) + { + this._States.Entity = null; + previousValue.Book = null; + } + this._States.Entity = value; + if ((value != null)) + { + value.Book = this; + } + this.SendPropertyChanged("State"); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} +#pragma warning restore 1591 diff --git a/Library/DataLayer/Database/Migrations/dbo.Books.sql b/Library/DataLayer/Database/Migrations/dbo.Books.sql new file mode 100644 index 0000000..6cda86a --- /dev/null +++ b/Library/DataLayer/Database/Migrations/dbo.Books.sql @@ -0,0 +1,10 @@ +CREATE TABLE [dbo].[Books] +( + [guid] VARCHAR(36) NOT NULL PRIMARY KEY, + [name] VARCHAR(50) NOT NULL, + [price] FLOAT NOT NULL, + [author] VARCHAR(50) NOT NULL, + [publisher] VARCHAR(50) NOT NULL, + [pages] INT NOT NULL, + [publicationDate] DATETIME NOT NULL +) diff --git a/Library/DataLayer/Database/Migrations/dbo.Events.sql b/Library/DataLayer/Database/Migrations/dbo.Events.sql new file mode 100644 index 0000000..085fb9f --- /dev/null +++ b/Library/DataLayer/Database/Migrations/dbo.Events.sql @@ -0,0 +1,10 @@ +CREATE TABLE [dbo].[Events] +( + [guid] VARCHAR(36) NOT NULL PRIMARY KEY, + [userGuid] VARCHAR(36) NOT NULL, + [stateGuid] VARCHAR(36) NOT NULL, + [type] NVARCHAR(50) NOT NULL, + [createdAt] DATETIME NOT NULL, + CONSTRAINT [FK_Events_ToUsersTable] FOREIGN KEY ([userGuid]) REFERENCES [Users]([guid]), + CONSTRAINT [DF_Events_ToStatesTable] FOREIGN KEY ([stateGuid]) REFERENCES [States]([guid]) +) diff --git a/Library/DataLayer/Database/Migrations/dbo.States.sql b/Library/DataLayer/Database/Migrations/dbo.States.sql new file mode 100644 index 0000000..d21b887 --- /dev/null +++ b/Library/DataLayer/Database/Migrations/dbo.States.sql @@ -0,0 +1,8 @@ +CREATE TABLE [dbo].[States] +( + [guid] VARCHAR(36) NOT NULL PRIMARY KEY, + [productGuid] VARCHAR(36) NOT NULL, + [quantity] INT NOT NULL, + [LastUpdatedDate] DATE NOT NULL, + CONSTRAINT [FK_States_ToProductTable] FOREIGN KEY (productGuid) REFERENCES [Books]([guid]) +) diff --git a/Library/DataLayer/Database/Migrations/dbo.Users.sql b/Library/DataLayer/Database/Migrations/dbo.Users.sql new file mode 100644 index 0000000..11666b8 --- /dev/null +++ b/Library/DataLayer/Database/Migrations/dbo.Users.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[Users] +( + [guid] VARCHAR(36) NOT NULL PRIMARY KEY, + [firstName] NVARCHAR(50) NOT NULL, + [lastName] NVARCHAR(50) NOT NULL, + [email] NVARCHAR(255) NOT NULL, + [balance] FLOAT NOT NULL, + [phoneNumber] NVARCHAR(15) NOT NULL +) diff --git a/Library/DataLayer/Implementations/Book.cs b/Library/DataLayer/Implementations/Book.cs index 3b30b73..2ae36b7 100644 --- a/Library/DataLayer/Implementations/Book.cs +++ b/Library/DataLayer/Implementations/Book.cs @@ -4,9 +4,9 @@ namespace DataLayer.Implementations { public class Book : IBook { - public Book(string name, double price, string author, string publisher, int pages, DateTime publicationDate) + public Book(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) { - Guid = System.Guid.NewGuid().ToString(); + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; Name = name; Price = price; Author = author; @@ -14,7 +14,7 @@ public Book(string name, double price, string author, string publisher, int page Pages = pages; PublicationDate = publicationDate; } - public string Guid { get; } + public string Guid { get; set; } public string Name { get; set; } public double Price { get; set; } public string Author { get; set; } diff --git a/Library/DataLayer/Implementations/DataContex.cs b/Library/DataLayer/Implementations/DataContex.cs index 9aaf936..a80a41d 100644 --- a/Library/DataLayer/Implementations/DataContex.cs +++ b/Library/DataLayer/Implementations/DataContex.cs @@ -1,26 +1,414 @@ using DataLayer.API; +using DataLayer.Database; +using System; namespace DataLayer.Implementations { public class DataContext : IDataContext { - public static IDataContext NewInstance() + public static IDataContext NewInstance(string? connectionString = null) { - return new DataContext(); + return new DataContext(connectionString); } - public List Users { get; set; } - public List Products { get; set; } - public List Events { get; set; } - public List States { get; set; } + private readonly string _connectionString; - private DataContext() + public DataContext(string? connectionString = null) { - Users = new List(); - Products = new List(); - Events = new List(); - States = new List(); + if (connectionString is null) + { + string _projectRootDir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.FullName; + string _DBRelativePath = @"DataLayer\Database\Database.mdf"; + string _DBPath = Path.Combine(_projectRootDir, _DBRelativePath); + this._connectionString = $@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={_DBPath};Integrated Security = True; Connect Timeout = 30;"; + } + else + { + this._connectionString = connectionString; + } } + #region User CRUD + + public async Task AddUserAsync(IUser user) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.User entity = new Database.User() + { + guid = user.Guid, + firstName = user.FirstName, + lastName = user.LastName, + email = user.Email, + balance = user.Balance, + phoneNumber = user.PhoneNumber + }; + + context.User.InsertOnSubmit(entity); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task GetUserAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.User? user = await Task.Run(() => + { + IQueryable query = context.User.Where(u => u.guid == guid); + + return query.FirstOrDefault(); + }); + + return user is not null ? new User(user.guid, user.firstName, user.lastName, user.email, user.balance, user.phoneNumber) : null; + } + } + + public async Task UpdateUserAsync(IUser user) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.User toUpdate = (from u in context.User where u.guid == user.Guid select u).FirstOrDefault()!; + + toUpdate.firstName = user.FirstName; + toUpdate.lastName = user.LastName; + toUpdate.email = user.Email; + toUpdate.balance = user.Balance; + toUpdate.phoneNumber = user.PhoneNumber; + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task DeleteUserAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.User toDelete = (from u in context.User where u.guid == guid select u).FirstOrDefault()!; + + context.User.DeleteOnSubmit(toDelete); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task> GetAllUsersAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + IQueryable usersQuery = from u in context.User + select + new User(u.guid, u.firstName, u.lastName, u.email, u.balance, u.phoneNumber) as IUser; + + return await Task.Run(() => usersQuery.ToDictionary(k => k.Guid)); + } + } + + public async Task GetUsersCountAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + return await Task.Run(() => context.User.Count()); + } + } + + #endregion + + #region Product CRUD + + public async Task AddProductAsync(IBook product) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Book entity = new Database.Book() + { + guid = product.Guid, + name = product.Name, + price = product.Price, + + author = (product as IBook)?.Author, + publisher = (product as IBook)?.Publisher, + pages = (int)(product as IBook)?.Pages, + publicationDate = (DateTime)(product as IBook)?.PublicationDate + }; + + context.Book.InsertOnSubmit(entity); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task GetProductAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Book? product = await Task.Run(() => + { + IQueryable query = + from p in context.Book + where p.guid == guid + select p; + + return query.FirstOrDefault(); + }); + + return product is not null ? new Book(product.guid, product.name, (double)product.price, product.author, product.publisher, product.pages, product.publicationDate) : null; + } + } + + public async Task UpdateProductAsync(IBook product) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Book toUpdate = (from p in context.Book where p.guid == product.Guid select p).FirstOrDefault()!; + + toUpdate.name = product.Name; + toUpdate.price = product.Price; + + toUpdate.author = (product as IBook)?.Author; + toUpdate.publisher = (product as IBook)?.Publisher; + toUpdate.pages = (int)(product as IBook)?.Pages; + toUpdate.publicationDate = (DateTime)(product as IBook)?.PublicationDate; + + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task DeleteProductAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Book toDelete = (from p in context.Book where p.guid == guid select p).FirstOrDefault()!; + + context.Book.DeleteOnSubmit(toDelete); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task> GetAllProductsAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + IQueryable productQuery = from p in context.Book + select + new Book(p.guid, p.name, (double)p.price, p.author, p.publisher, p.pages, p.publicationDate) as IBook; + + return await Task.Run(() => productQuery.ToDictionary(k => k.Guid)); + } + } + + public async Task GetProductsCountAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + return await Task.Run(() => context.Book.Count()); + } + } + + #endregion + + + #region State CRUD + + public async Task AddStateAsync(IState state) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.State entity = new Database.State() + { + guid = state.Guid, + productGuid = state.ProductGuid, + quantity = state.Quantity + }; + + context.State.InsertOnSubmit(entity); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task GetStateAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.State? state = await Task.Run(() => + { + IQueryable query = + from s in context.State + where s.guid == guid + select s; + + return query.FirstOrDefault(); + }); + + return state is not null ? new State(state.guid, state.productGuid, state.quantity) : null; + } + } + + public async Task UpdateStateAsync(IState state) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.State toUpdate = (from s in context.State where s.guid == state.Guid select s).FirstOrDefault()!; + + toUpdate.productGuid = state.ProductGuid; + toUpdate.quantity = state.Quantity; + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task DeleteStateAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.State toDelete = (from s in context.State where s.guid == guid select s).FirstOrDefault()!; + + context.State.DeleteOnSubmit(toDelete); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task> GetAllStatesAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + IQueryable stateQuery = from s in context.State + select + new State(s.guid, s.productGuid, s.quantity) as IState; + + return await Task.Run(() => stateQuery.ToDictionary(k => k.Guid)); + } + } + + public async Task GetStatesCountAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + return await Task.Run(() => context.State.Count()); + } + } + + #endregion + + + #region Event CRUD + + public async Task AddEventAsync(IEvent even) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Event entity = new Database.Event() + { + guid = even.Guid, + stateGuid = even.StateGuid, + userGuid = even.UserGuid, + createdAt = even.CreatedAt, + type = even.Type, + }; + + context.Event.InsertOnSubmit(entity); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task GetEventAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Event? even = await Task.Run(() => + { + IQueryable query = + from e in context.Event + where e.guid == guid + select e; + + return query.FirstOrDefault(); + }); + + return even is not null ? new Event(even.guid, even.stateGuid, even.userGuid, even.createdAt, even.type) : null; + } + + } + + public async Task UpdateEventAsync(IEvent even) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Event toUpdate = (from e in context.Event where e.guid == even.Guid select e).FirstOrDefault()!; + + toUpdate.stateGuid = even.StateGuid; + toUpdate.userGuid = even.UserGuid; + toUpdate.createdAt = even.CreatedAt; + toUpdate.type = even.Type; + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task DeleteEventAsync(string guid) + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + Database.Event toDelete = (from e in context.Event where e.guid == guid select e).FirstOrDefault()!; + + context.Event.DeleteOnSubmit(toDelete); + + await Task.Run(() => context.SubmitChanges()); + } + } + + public async Task> GetAllEventsAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + IQueryable eventQuery = from e in context.Event + select + new Event(e.guid, e.stateGuid, e.userGuid, e.createdAt, e.type) as IEvent; + + return await Task.Run(() => eventQuery.ToDictionary(k => k.Guid)); + } + } + + public async Task GetEventsCountAsync() + { + using (LibraryDataClassesDataContext context = new LibraryDataClassesDataContext(_connectionString)) + { + return await Task.Run(() => context.Event.Count()); + } + } + + #endregion + + + #region Helpers + + public async Task CheckIfUserExists(string guid) + { + return (await GetUserAsync(guid)) != null; + } + + public async Task CheckIfProductExists(string guid) + { + return (await GetProductAsync(guid)) != null; + } + + public async Task CheckIfStateExists(string guid) + { + return (await GetStateAsync(guid)) != null; + } + + public async Task CheckIfEventExists(string guid, string type) + { + return (await GetEventAsync(guid)) != null; + } + + #endregion + } } \ No newline at end of file diff --git a/Library/DataLayer/Implementations/DataRepository.cs b/Library/DataLayer/Implementations/DataRepository.cs index 29fac34..107d7f4 100644 --- a/Library/DataLayer/Implementations/DataRepository.cs +++ b/Library/DataLayer/Implementations/DataRepository.cs @@ -1,4 +1,5 @@ using DataLayer.API; +using DataLayer.Database; namespace DataLayer.Implementations { @@ -6,11 +7,12 @@ public class DataRepository : IDataRepository { private IDataContext _dataContext; - public static IDataRepository NewInstance(IDataContext dataContext) + public static IDataRepository NewInstance(IDataContext? dataContext = null) { - return new DataRepository(dataContext); + return new DataRepository(dataContext ?? DataContext.NewInstance()); } - private DataRepository(IDataContext dataContext) + + public DataRepository(IDataContext dataContext) { _dataContext = dataContext; } @@ -19,159 +21,304 @@ public void Seed(IDataFiller dataSeeder) { foreach (IUser user in dataSeeder.GetGeneratedUsers()) { - AddUser(user); + // TODO } foreach (IState state in dataSeeder.GetGeneratedStates()) { - AddState(state); + // TODO } foreach (IProduct product in dataSeeder.GetGeneratedProducts()) { - AddProduct(product); + // TODO } foreach (IEvent @event in dataSeeder.GetGeneratedEvents()) { - AddEvent(@event); + // TODO } } - #region User - public void AddUser(IUser user) + #region User CRUD + + public async Task AddUserAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) { - _dataContext.Users.Add(user); + IUser user = new User(guid, firstName, lastName, email, balance, phoneNumber); + + await _dataContext.AddUserAsync(user); } - public IUser GetUser(string guid) + + public async Task GetUserAsync(string guid) { - IUser? user = _dataContext.Users.FirstOrDefault(u => u.Guid == guid) ?? throw new Exception("User does not exist"); + IUser? user = await _dataContext.GetUserAsync(guid) ?? throw new Exception("This user does not exist!"); return user; } - public List GetAllUsers() + + public async Task UpdateUserAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) { - return _dataContext.Users; + IUser user = new User(guid, firstName, lastName, email, balance, phoneNumber); + + if (!await CheckIfUserExists(user.Guid)) + throw new Exception("This user does not exist"); + + await _dataContext.UpdateUserAsync(user); } - public void RemoveUser(string guid) + + public async Task DeleteUserAsync(string guid) { - IUser user = _dataContext.Users.FirstOrDefault(user => user.Guid == guid) ?? throw new Exception("User does not exist"); + if (!await CheckIfUserExists(guid)) + throw new Exception("This user does not exist"); - _dataContext.Users.Remove(user); + await _dataContext.DeleteUserAsync(guid); } - public bool DoesUserExist(string guid) + + public async Task> GetAllUsersAsync() { - return _dataContext.Users.Exists(e => e.Guid == guid); + return await _dataContext.GetAllUsersAsync(); } - public void UpdateUser(IUser updateUser) - { - IUser? userToBeUpdated = _dataContext.Users.FirstOrDefault(u => u.Guid == updateUser.Guid); - if (userToBeUpdated == null) - { - throw new Exception("Cannot update user that does not exist"); - } - - userToBeUpdated = updateUser; + public async Task GetUsersCountAsync() + { + return await _dataContext.GetUsersCountAsync(); } #endregion - #region Product - public void AddProduct(IProduct product) + + #region Product CRUD + + public async Task AddProductAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) { - _dataContext.Products.Add(product); + IBook product = new Book(guid, name, price, author, publisher, pages, publicationDate); + + await _dataContext.AddProductAsync(product); } - public IProduct GetProduct(string guid) + + public async Task GetProductAsync(string guid) { - IProduct product = _dataContext.Products.FirstOrDefault(product => product.Guid == guid) ?? throw new Exception("Product does not exist"); + IBook? product = await _dataContext.GetProductAsync(guid); + + if (product is null) + throw new Exception("This product does not exist!"); return product; } - public List GetAllProducts() + + public async Task UpdateProductAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) { - return _dataContext.Products; + IBook product = new Book(guid, name, price, author, publisher, pages, publicationDate); + + if (!await CheckIfProductExists(product.Guid)) + throw new Exception("This product does not exist"); + + await _dataContext.UpdateProductAsync(product); } - public IProduct GetProductByState(string stateGuid) + + public async Task DeleteProductAsync(string guid) { - IProduct? product = _dataContext.States.FirstOrDefault(state => state.Guid == stateGuid)?.Product; - if (product == null) - { - throw new Exception("Product does not exist"); - } + if (!await CheckIfProductExists(guid)) + throw new Exception("This product does not exist"); - return product; + await _dataContext.DeleteProductAsync(guid); } - public bool DoesProductExist(string guid) + + public async Task> GetAllProductsAsync() { - return _dataContext.Products.Exists(e => e.Guid == guid); + return await _dataContext.GetAllProductsAsync(); } - public void RemoveProduct(string guid) - { - IProduct product = _dataContext.Products.FirstOrDefault(product => product.Guid == guid) ?? throw new Exception("Product does not exist"); - _dataContext.Products.Remove(product); + public async Task GetProductsCountAsync() + { + return await _dataContext.GetProductsCountAsync(); } + #endregion - #region Event - public void AddEvent(IEvent @event) + + #region State CRUD + + public async Task AddStateAsync(string guid, string productGuid, int quantity) { - _dataContext.Events.Add(@event); + if (!await _dataContext.CheckIfProductExists(productGuid)) + throw new Exception("This product does not exist!"); + + if (quantity < 0) + throw new Exception("Product's quantity must be number greater that 0!"); + + IState state = new State(guid, productGuid, quantity); + + await _dataContext.AddStateAsync(state); } - public IEvent GetEvent(string guid) + + public async Task GetStateAsync(string guid) { - IEvent @event = _dataContext.Events.FirstOrDefault(@event => @event.Guid == guid) ?? throw new Exception("Event does not exist"); + IState? state = await _dataContext.GetStateAsync(guid); + + if (state is null) + throw new Exception("This state does not exist!"); - return @event; + return state; } - public List GetAllEvents() + + public async Task UpdateStateAsync(string guid, string productGuid, int quantity) { - return _dataContext.Events; + if (!await _dataContext.CheckIfProductExists(productGuid)) + throw new Exception("This product does not exist!"); + + if (quantity <= 0) + throw new Exception("Product's quantity must be number greater that 0!"); + + IState state = new State(guid, productGuid, quantity); + + if (!await CheckIfStateExists(state.Guid)) + throw new Exception("This state does not exist"); + + await _dataContext.UpdateStateAsync(state); } - public List GetEventsByUser(string userGuid) + + public async Task DeleteStateAsync(string guid) { - List events = _dataContext.Events.Where(@event => @event.User.Guid == userGuid).ToList(); + if (!await CheckIfStateExists(guid)) + throw new Exception("This state does not exist"); - return events; + await _dataContext.DeleteStateAsync(guid); } - public List GetEventsByProduct(string productGuid) + + public async Task> GetAllStatesAsync() { - List events = _dataContext.Events.Where(@event => @event.State.Product.Guid == productGuid).ToList(); + return await _dataContext.GetAllStatesAsync(); + } - return events; + public async Task GetStatesCountAsync() + { + return await _dataContext.GetStatesCountAsync(); } - public List GetEventsByState(string stateGuid) + + #endregion + + + #region Event CRUD + + public async Task AddEventAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type) { - List events = _dataContext.Events.Where(@event => @event.State.Guid == stateGuid).ToList(); + IUser user = await GetUserAsync(userGuid); + IState state = await GetStateAsync(stateGuid); + IProduct product = await GetProductAsync(state.ProductGuid); + + IEvent newEvent = new Event( guid, stateGuid, userGuid, createdAt, type); + + switch (type) + { + case "RentEvent": + if (state.Quantity == 0) + throw new Exception("Such Product can't be rented!"); + + await UpdateStateAsync(stateGuid, product.Guid, state.Quantity - 1); + await UpdateUserAsync(userGuid, user.FirstName, user.LastName, user.Email, user.Balance, user.PhoneNumber); + + break; + + case "ReturnEvent": + Dictionary events = await GetAllEventsAsync(); + Dictionary states = await GetAllStatesAsync(); - return events; + int copiesBought = 0; + + foreach + ( + IEvent even in + from evennt in events.Values + from statee in states.Values + where evennt.UserGuid == user.Guid && + evennt.StateGuid == statee.Guid && + statee.ProductGuid == product.Guid + select evennt + ) + if (even.Type == "PurchaseEvent") + copiesBought++; + else if (even.Type == "ReturnEvent") + copiesBought--; + + copiesBought--; + + if (copiesBought < 0) + { + throw new Exception("You do not own this product!"); + } + + await UpdateStateAsync(stateGuid, product.Guid, state.Quantity + 1); + + break; + case "SupplyEvent": + + await this.UpdateStateAsync(stateGuid, product.Guid, state.Quantity + 1); + + break; + + default: + throw new Exception("This Event Type is not handled"); + } + + await _dataContext.AddEventAsync(newEvent); } - public void RemoveEvent(string guid) + + public async Task GetEventAsync(string guid) { - IEvent @event = _dataContext.Events.FirstOrDefault(@event => @event.Guid == guid) ?? throw new Exception("Event does not exist"); + IEvent? even = await _dataContext.GetEventAsync(guid); - _dataContext.Events.Remove(@event); + return even is null ? throw new Exception("This event does not exist!") : even; } - #endregion - #region State - public void AddState(IState state) + public async Task UpdateEventAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type) { - _dataContext.States.Add(state); + IEvent newEvent = new Event(guid, stateGuid, userGuid, createdAt, type); + + if (!await CheckIfEventExists(newEvent.Guid, type)) + throw new Exception("This event does not exist"); + + await _dataContext.UpdateEventAsync(newEvent); } - public List GetAllStates() + + public async Task DeleteEventAsync(string guid) { - return _dataContext.States; + if (!await CheckIfEventExists(guid, "RentEvent")) + throw new Exception("This event does not exist"); + + await _dataContext.DeleteEventAsync(guid); } - public IState GetState(string guid) + + public async Task> GetAllEventsAsync() { - IState state = _dataContext.States.FirstOrDefault(state => state.Guid == guid) ?? throw new Exception("State does not exist"); + return await _dataContext.GetAllEventsAsync(); + } - return state; + public async Task GetEventsCountAsync() + { + return await _dataContext.GetEventsCountAsync(); + } + + #endregion + + + #region Utils + + public async Task CheckIfUserExists(string guid) + { + return await _dataContext.CheckIfUserExists(guid); } - public void RemoveState(string guid) + + public async Task CheckIfProductExists(string guid) { - IState state = _dataContext.States.FirstOrDefault(state => state.Guid == guid) ?? throw new Exception("State does not exist"); + return await _dataContext.CheckIfProductExists(guid); + } - _dataContext.States.Remove(state); + public async Task CheckIfStateExists(string guid) + { + return await _dataContext.CheckIfStateExists(guid); + } + + public async Task CheckIfEventExists(string guid, string type) + { + return await _dataContext.CheckIfEventExists(guid, type); } #endregion } diff --git a/Library/DataLayer/Implementations/Event.cs b/Library/DataLayer/Implementations/Event.cs new file mode 100644 index 0000000..b28c037 --- /dev/null +++ b/Library/DataLayer/Implementations/Event.cs @@ -0,0 +1,26 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class Event : IEvent + { + public Event(string guid, string stateGuid, string userGuid, DateTime createdAt, string type) + { + this.Guid = guid; + this.StateGuid = stateGuid; + this.UserGuid = userGuid; + this.CreatedAt = createdAt; + this.Type = type; + } + + public string Guid { get; set; } + + public string StateGuid { get; set; } + + public string UserGuid { get; set; } + + public DateTime CreatedAt { get; set; } + + public string Type { get; set; } + } +} diff --git a/Library/DataLayer/Implementations/Events/Borrow.cs b/Library/DataLayer/Implementations/Events/Borrow.cs deleted file mode 100644 index 942acaa..0000000 --- a/Library/DataLayer/Implementations/Events/Borrow.cs +++ /dev/null @@ -1,36 +0,0 @@ -using DataLayer.API; - -namespace DataLayer.Implementations.Events -{ - public class Borrow : IEvent - { - public Borrow(IUser user, IState state, string? guid = null) - { - Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; - User = user; - State = state; - CreatedAt = DateTime.Now; - - // Check if the product is available - if (state.Quantity <= 0) - { - throw new Exception("Product is not available"); - } - - // Should we allow borrowing the product if the user already has it? - - // Check if user has enough credits to borrow the product - if (user.Balance < state.Product.Price) - { - throw new Exception("User balance is not enough to borrow the product"); - } - - user.ProductsDic.Add(state.Product.Guid, state.Product); - state.Quantity--; - } - public string Guid { get; } - public IUser User { get; } - public IState State { get; } - public DateTime CreatedAt { get; } - } -} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/Events/Delivery.cs b/Library/DataLayer/Implementations/Events/Delivery.cs deleted file mode 100644 index f555592..0000000 --- a/Library/DataLayer/Implementations/Events/Delivery.cs +++ /dev/null @@ -1,27 +0,0 @@ -using DataLayer.API; - -namespace DataLayer.Implementations.Events -{ - public class Delivery : IEvent - { - public Delivery(IUser user, IState state, int amount, string? guid = null) - { - Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; - User = user; - State = state; - CreatedAt = DateTime.Now; - - if(amount <= 0) - { - throw new Exception("Amount must be greater than 0"); - } - - state.Quantity += amount; - } - - public string Guid { get; } - public IUser User { get; } - public IState State { get; } - public DateTime CreatedAt { get; } - } -} diff --git a/Library/DataLayer/Implementations/Events/Return.cs b/Library/DataLayer/Implementations/Events/Return.cs deleted file mode 100644 index fde3417..0000000 --- a/Library/DataLayer/Implementations/Events/Return.cs +++ /dev/null @@ -1,28 +0,0 @@ -using DataLayer.API; - -namespace DataLayer.Implementations.Events -{ - public class Return : IEvent - { - public Return(IUser user, IState state, string? guid = null) - { - Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; - User = user; - State = state; - CreatedAt = DateTime.Now; - - // Check if the product is in the user's inventory because we can't return a product that we don't have - if (!user.ProductsDic.ContainsKey(state.Product.Guid)) - { - throw new Exception("Product not found in user's inventory"); - } - - user.ProductsDic.Remove(state.Product.Guid); - state.Quantity++; - } - public string Guid { get; } - public IUser User { get; } - public IState State { get; } - public DateTime CreatedAt { get; } - } -} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/State.cs b/Library/DataLayer/Implementations/State.cs index 8240a04..41453bc 100644 --- a/Library/DataLayer/Implementations/State.cs +++ b/Library/DataLayer/Implementations/State.cs @@ -5,26 +5,26 @@ namespace DataLayer.Implementations public class State : IState { private int _quantity; - private DateTime _lastUpdatedDate; - public State(IProduct product, int quantity = 0, string? guid = null) + + public State(string guid, string productGuid, int quantity = 0) { Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; - Product = product; + ProductGuid = productGuid; Quantity = quantity; - _lastUpdatedDate = DateTime.Now; } - public IProduct Product { get; set; } + public int Quantity + { get => _quantity; set { _quantity = value; - _lastUpdatedDate = DateTime.Now; } } - public DateTime LastUpdatedDate { get => _lastUpdatedDate; } + + public string Guid { get; set; } + public string ProductGuid{ get; set; } public double Price { get; set; } - public string Guid { get; } } } \ No newline at end of file diff --git a/Library/DataLayer/Implementations/User.cs b/Library/DataLayer/Implementations/User.cs index 916033f..f6c466f 100644 --- a/Library/DataLayer/Implementations/User.cs +++ b/Library/DataLayer/Implementations/User.cs @@ -4,18 +4,17 @@ namespace DataLayer.Implementations { public class User : IUser { - public User(string firstName, string lastName, string email, double balance, int phoneNumber, Dictionary? productsDic) + public User(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) { - Guid = System.Guid.NewGuid().ToString(); + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; FirstName = firstName; LastName = lastName; Email = email; Balance = balance; PhoneNumber = phoneNumber; - ProductsDic = productsDic ?? new Dictionary(); } - public string Guid { get; } + public string Guid { get; set; } public string FirstName { get; set; } @@ -25,8 +24,6 @@ public User(string firstName, string lastName, string email, double balance, int public double Balance { get; set; } - public int PhoneNumber { get; set; } - - public Dictionary ProductsDic { get; set; } + public string PhoneNumber { get; set; } } } \ No newline at end of file diff --git a/Library/LogicLayer/API/IDataService.cs b/Library/LogicLayer/API/IDataService.cs index 9fee60a..f4a44c6 100644 --- a/Library/LogicLayer/API/IDataService.cs +++ b/Library/LogicLayer/API/IDataService.cs @@ -1,5 +1,4 @@ using DataLayer.API; -using DataLayer.Implementations.Events; namespace LogicLayer.API { diff --git a/Library/Presentation/App.xaml b/Library/Presentation/App.xaml new file mode 100644 index 0000000..7b86cf3 --- /dev/null +++ b/Library/Presentation/App.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Library/Presentation/App.xaml.cs b/Library/Presentation/App.xaml.cs new file mode 100644 index 0000000..7b60e4e --- /dev/null +++ b/Library/Presentation/App.xaml.cs @@ -0,0 +1,13 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace Presentation; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} + diff --git a/Library/Presentation/AssemblyInfo.cs b/Library/Presentation/AssemblyInfo.cs new file mode 100644 index 0000000..cc29e7f --- /dev/null +++ b/Library/Presentation/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/Library/Presentation/Assets/AppLogo.jpg b/Library/Presentation/Assets/AppLogo.jpg new file mode 100644 index 0000000..47779de Binary files /dev/null and b/Library/Presentation/Assets/AppLogo.jpg differ diff --git a/Library/Presentation/IErrorInformer.cs b/Library/Presentation/IErrorInformer.cs new file mode 100644 index 0000000..6b13222 --- /dev/null +++ b/Library/Presentation/IErrorInformer.cs @@ -0,0 +1,11 @@ +namespace Presentation +{ + public interface IErrorInformer + { + void InformError(string message); + + void InformSuccess(string message); + + string GetRecentMessage(); + } +} diff --git a/Library/Presentation/Model/API/IEventModel.cs b/Library/Presentation/Model/API/IEventModel.cs new file mode 100644 index 0000000..649e525 --- /dev/null +++ b/Library/Presentation/Model/API/IEventModel.cs @@ -0,0 +1,11 @@ +namespace Presentation.Model.API +{ + public interface IEventModel + { + string Guid { get; set; } + string UserGuid { get; set; } + string StateGuid { get; set; } + string Type { get; set; } + DateTime CreatedAt { get; set; } + } +} diff --git a/Library/Presentation/Model/API/IEventModelOperation.cs b/Library/Presentation/Model/API/IEventModelOperation.cs new file mode 100644 index 0000000..9b22897 --- /dev/null +++ b/Library/Presentation/Model/API/IEventModelOperation.cs @@ -0,0 +1,25 @@ +using Presentation.Model.Implementation; +using Service.API; + +namespace Presentation.Model.API +{ + public interface IEventModelOperation + { + static IEventModelOperation CreateModelOperation(IEventCRUD? eventCrud = null) + { + return new EventModelOperation(eventCrud ?? IEventCRUD.CreateEventCRUD()); + } + + Task AddAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type); + + Task GetAsync(string guid, string type); + + Task UpdateAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type); + + Task DeleteAsync(string guid); + + Task> GetAllAsync(); + + Task GetCountAsync(); + } +} diff --git a/Library/Presentation/Model/API/IProductModel.cs b/Library/Presentation/Model/API/IProductModel.cs new file mode 100644 index 0000000..58a1bcc --- /dev/null +++ b/Library/Presentation/Model/API/IProductModel.cs @@ -0,0 +1,13 @@ +namespace Presentation.Model.API +{ + public interface IProductModel + { + string Guid { get; set; } + string Name { get; set; } + double Price { get; set; } + string Author { get; set; } + string Publisher { get; set; } + int Pages { get; set; } + DateTime PublicationDate { get; set; } + } +} diff --git a/Library/Presentation/Model/API/IProductModelOperation.cs b/Library/Presentation/Model/API/IProductModelOperation.cs new file mode 100644 index 0000000..ae9f5fd --- /dev/null +++ b/Library/Presentation/Model/API/IProductModelOperation.cs @@ -0,0 +1,25 @@ +using Presentation.Model.Implementation; +using Service.API; + +namespace Presentation.Model.API +{ + public interface IProductModelOperation + { + static IProductModelOperation CreateModelOperation(IProductCRUD? productCrud = null) + { + return new ProductModelOperation(productCrud ?? IProductCRUD.CreateBookCRUD()); + } + + Task AddAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate); + + Task GetAsync(string guid); + + Task UpdateAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate); + + Task DeleteAsync(string guid); + + Task> GetAllAsync(); + + Task GetCountAsync(); + } +} diff --git a/Library/Presentation/Model/API/IStateModel.cs b/Library/Presentation/Model/API/IStateModel.cs new file mode 100644 index 0000000..6c60c1b --- /dev/null +++ b/Library/Presentation/Model/API/IStateModel.cs @@ -0,0 +1,9 @@ +namespace Presentation.Model.API +{ + public interface IStateModel + { + string Guid { get; set; } + string ProductGuid { get; set; } + int Quantity { get; set; } + } +} diff --git a/Library/Presentation/Model/API/IStateModelOperation.cs b/Library/Presentation/Model/API/IStateModelOperation.cs new file mode 100644 index 0000000..2400de4 --- /dev/null +++ b/Library/Presentation/Model/API/IStateModelOperation.cs @@ -0,0 +1,25 @@ +using Presentation.Model.Implementation; +using Service.API; + +namespace Presentation.Model.API +{ + public interface IStateModelOperation + { + static IStateModelOperation CreateModelOperation(IStateCRUD? stateCrud = null) + { + return new StateModelOperation(stateCrud ?? IStateCRUD.CreateStateCRUD()); + } + + Task AddAsync(string guid, string productGuid, int quantity); + + Task GetAsync(string guid); + + Task UpdateAsync(string guid, string productGuid, int quantity); + + Task DeleteAsync(string guid); + + Task> GetAllAsync(); + + Task GetCountAsync(); + } +} diff --git a/Library/Presentation/Model/API/IUserModel.cs b/Library/Presentation/Model/API/IUserModel.cs new file mode 100644 index 0000000..ad5fb53 --- /dev/null +++ b/Library/Presentation/Model/API/IUserModel.cs @@ -0,0 +1,12 @@ +namespace Presentation.Model.API +{ + public interface IUserModel + { + string Guid { get; set; } + string FirstName { get; set; } + string LastName { get; set; } + string Email { get; set; } + double Balance { get; set; } + string PhoneNumber { get; set; } + } +} diff --git a/Library/Presentation/Model/API/IUserModelOperation.cs b/Library/Presentation/Model/API/IUserModelOperation.cs new file mode 100644 index 0000000..5f1ae39 --- /dev/null +++ b/Library/Presentation/Model/API/IUserModelOperation.cs @@ -0,0 +1,26 @@ +using Presentation.Model.Implementation; +using Service.API; +using Service.Implementation; + +namespace Presentation.Model.API +{ + public interface IUserModelOperation + { + static IUserModelOperation CreateModelOperation(IUserCRUD? userCrud = null) + { + return new UserModelOperation(userCrud); + } + + Task AddAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber); + + Task GetAsync(string guid); + + Task UpdateAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber); + + Task DeleteAsync(string guid); + + Task> GetAllAsync(); + + Task GetCountAsync(); + } +} diff --git a/Library/Presentation/Model/Implementation/EventModel .cs b/Library/Presentation/Model/Implementation/EventModel .cs new file mode 100644 index 0000000..525b0b1 --- /dev/null +++ b/Library/Presentation/Model/Implementation/EventModel .cs @@ -0,0 +1,28 @@ +using Presentation.Model.API; +using System; + + +namespace Presentation.Model.Implementation +{ + internal class EventModel : IEventModel + { + public EventModel(string guid, string stateGuid, string userGuid, DateTime createdAt, string type) + { + Guid = guid; + StateGuid = stateGuid; + UserGuid = userGuid; + CreatedAt = createdAt; + Type = type; + } + + public string Guid { get; set; } + + public string StateGuid { get; set; } + + public string UserGuid { get; set; } + + public DateTime CreatedAt { get; set; } + + public string Type { get; set; } + } +} diff --git a/Library/Presentation/Model/Implementation/EventModelOperation .cs b/Library/Presentation/Model/Implementation/EventModelOperation .cs new file mode 100644 index 0000000..3de8733 --- /dev/null +++ b/Library/Presentation/Model/Implementation/EventModelOperation .cs @@ -0,0 +1,59 @@ +using System; +using Presentation.Model.API; +using Service.API; + + +namespace Presentation.Model.Implementation +{ + internal class EventModelOperation : IEventModelOperation + { + private IEventCRUD _eventCRUD; + + public EventModelOperation(IEventCRUD? eventCrud = null) + { + _eventCRUD = eventCrud ?? IEventCRUD.CreateEventCRUD(); + } + + private IEventModel Map(IEventDTO even) + { + return new EventModel(even.Guid, even.StateGuid, even.UserGuid, even.CreatedAt, even.Type); + } + + public async Task AddAsync(string guid, string stateGuid, string userGuid, DateTime createdAt, string type) + { + await _eventCRUD.AddEventAsync(guid, stateGuid, userGuid, createdAt, type); + } + + public async Task GetAsync(string guid, string type) + { + return Map(await _eventCRUD.GetEventAsync(guid)); + } + + public async Task UpdateAsync(string guid, string stateGuid, string userIGuid, DateTime createdAt, string type) + { + await _eventCRUD.UpdateEventAsync(guid, stateGuid, userIGuid, createdAt, type); + } + + public async Task DeleteAsync(string guid) + { + await _eventCRUD.DeleteEventAsync(guid); + } + + public async Task> GetAllAsync() + { + Dictionary result = new Dictionary(); + + foreach (IEventDTO even in (await _eventCRUD.GetAllEventsAsync()).Values) + { + result.Add(even.Guid, Map(even)); + } + + return result; + } + + public async Task GetCountAsync() + { + return await _eventCRUD.GetEventsCountAsync(); + } + } +} diff --git a/Library/Presentation/Model/Implementation/ProductModel.cs b/Library/Presentation/Model/Implementation/ProductModel.cs new file mode 100644 index 0000000..51b918a --- /dev/null +++ b/Library/Presentation/Model/Implementation/ProductModel.cs @@ -0,0 +1,26 @@ +using Presentation.Model.API; +using Service.API; + +namespace Presentation.Model.Implementation +{ + internal class ProductModel : IProductModel + { + public ProductModel(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + Name = name; + Price = price; + Author = author; + Publisher = publisher; + Pages = pages; + PublicationDate = publicationDate; + } + public string Guid { get; set; } + public string Name { get; set; } + public double Price { get; set; } + public string Author { get; set; } + public string Publisher { get; set; } + public int Pages { get; set; } + public DateTime PublicationDate { get; set; } + } +} diff --git a/Library/Presentation/Model/Implementation/ProductModelOperation.cs b/Library/Presentation/Model/Implementation/ProductModelOperation.cs new file mode 100644 index 0000000..0c95087 --- /dev/null +++ b/Library/Presentation/Model/Implementation/ProductModelOperation.cs @@ -0,0 +1,58 @@ +using System; +using Presentation.Model.API; +using Service.API; + +namespace Presentation.Model.Implementation +{ + internal class ProductModelOperation : IProductModelOperation + { + private IProductCRUD _productCRUD; + + public ProductModelOperation(IProductCRUD? productCrud = null) + { + _productCRUD = productCrud ?? IProductCRUD.CreateBookCRUD(); + } + + private IProductModel Map(IProductDTO product) + { + return new ProductModel(product.Guid, product.Name, product.Price, product.Author, product.Publisher, product.Pages, product.PublicationDate); + } + + public async Task AddAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) + { + await _productCRUD.AddProductAsync(guid, name, price, author, publisher, pages, publicationDate); + } + + public async Task GetAsync(string guid) + { + return Map(await _productCRUD.GetProductAsync(guid)); + } + + public async Task UpdateAsync(string guid, string name, double price, string author, string publisher, int pages, DateTime publicationDate) + { + await _productCRUD.UpdateProductAsync(guid, name, price, author, publisher, pages, publicationDate); + } + + public async Task DeleteAsync(string guid) + { + await _productCRUD.DeleteProductAsync(guid); + } + + public async Task> GetAllAsync() + { + Dictionary result = new Dictionary(); + + foreach (IProductDTO product in (await _productCRUD.GetAllProductsAsync()).Values) + { + result.Add(product.Guid, Map(product)); + } + + return result; + } + + public async Task GetCountAsync() + { + return await _productCRUD.GetProductsCountAsync(); + } + } +} diff --git a/Library/Presentation/Model/Implementation/StateModel.cs b/Library/Presentation/Model/Implementation/StateModel.cs new file mode 100644 index 0000000..b312058 --- /dev/null +++ b/Library/Presentation/Model/Implementation/StateModel.cs @@ -0,0 +1,32 @@ +using Presentation.Model.API; +using System; + + +namespace Presentation.Model.Implementation +{ + internal class StateModel : IStateModel + { + private int _quantity; + + public StateModel(string guid, string productGuid, int quantity = 0) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + ProductGuid = productGuid; + Quantity = quantity; + } + + public int Quantity + + { + get => _quantity; + set + { + _quantity = value; + } + } + + public string Guid { get; set; } + public string ProductGuid { get; set; } + public double Price { get; set; } + } +} diff --git a/Library/Presentation/Model/Implementation/StateModelOperation .cs b/Library/Presentation/Model/Implementation/StateModelOperation .cs new file mode 100644 index 0000000..184d5f2 --- /dev/null +++ b/Library/Presentation/Model/Implementation/StateModelOperation .cs @@ -0,0 +1,62 @@ +using Presentation.Model.API; +using Service.API; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Presentation.Model.Implementation +{ + internal class StateModelOperation : IStateModelOperation + { + private IStateCRUD _stateCrud; + + public StateModelOperation(IStateCRUD? stateCrud = null) + { + _stateCrud = stateCrud ?? IStateCRUD.CreateStateCRUD(); + } + + private IStateModel Map(IStateDTO state) + { + return new StateModel(state.Guid, state.ProductGuid, state.Quantity); + } + + public async Task AddAsync(string guid, string productGuid, int quantity) + { + await _stateCrud.AddStateAsync(guid, productGuid, quantity); + } + + public async Task GetAsync(string guid) + { + return Map(await _stateCrud.GetStateAsync(guid)); + } + + public async Task UpdateAsync(string guid, string productGuid, int quantity) + { + await _stateCrud.UpdateStateAsync(guid, productGuid, quantity); + } + + public async Task DeleteAsync(string guid) + { + await _stateCrud.DeleteStateAsync(guid); + } + + public async Task> GetAllAsync() + { + Dictionary result = new Dictionary(); + + foreach (IStateDTO state in (await _stateCrud.GetAllStatesAsync()).Values) + { + result.Add(state.Guid, Map(state)); + } + + return result; + } + + public async Task GetCountAsync() + { + return await _stateCrud.GetStatesCountAsync(); + } + } +} diff --git a/Library/Presentation/Model/Implementation/UserModel.cs b/Library/Presentation/Model/Implementation/UserModel.cs new file mode 100644 index 0000000..6cce541 --- /dev/null +++ b/Library/Presentation/Model/Implementation/UserModel.cs @@ -0,0 +1,34 @@ +using Presentation.Model.API; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Presentation.Model.Implementation +{ + internal class UserModel : IUserModel + { + public UserModel(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + FirstName = firstName; + LastName = lastName; + Email = email; + Balance = balance; + PhoneNumber = phoneNumber; + } + + public string Guid { get; set; } + + public string FirstName { get; set; } + + public string LastName { get; set; } + + public string Email { get; set; } + + public double Balance { get; set; } + + public string PhoneNumber { get; set; } + } +} diff --git a/Library/Presentation/Model/Implementation/UserModelOperation.cs b/Library/Presentation/Model/Implementation/UserModelOperation.cs new file mode 100644 index 0000000..15a0988 --- /dev/null +++ b/Library/Presentation/Model/Implementation/UserModelOperation.cs @@ -0,0 +1,62 @@ +using Presentation.Model.API; +using Service.API; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Presentation.Model.Implementation +{ + internal class UserModelOperation : IUserModelOperation + { + private IUserCRUD _userCRUD; + + public UserModelOperation(IUserCRUD? userCrud) + { + _userCRUD = userCrud ?? IUserCRUD.CreateUserCRUD(); + } + + private IUserModel Map(IUserDTO user) + { + return new UserModel(user.Guid, user.FirstName, user.LastName, user.Email, user.Balance, user.PhoneNumber); + } + + public async Task AddAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) + { + await _userCRUD.AddUserAsync(guid, firstName, lastName, email, balance, phoneNumber); + } + + public async Task GetAsync(string guid) + { + return Map(await _userCRUD.GetUserAsync(guid)); + } + + public async Task UpdateAsync(string guid, string firstName, string lastName, string email, double balance, string phoneNumber) + { + await _userCRUD.UpdateUserAsync(guid, firstName, lastName, email, balance, phoneNumber); + } + + public async Task DeleteAsync(string guid) + { + await _userCRUD.DeleteUserAsync(guid); + } + + public async Task> GetAllAsync() + { + Dictionary result = new Dictionary(); + + foreach (IUserDTO user in (await _userCRUD.GetAllUsersAsync()).Values) + { + result.Add(user.Guid, Map(user)); + } + + return result; + } + + public async Task GetCountAsync() + { + return await _userCRUD.GetUsersCountAsync(); + } + } +} diff --git a/Library/Presentation/PopupErrorInformer.cs b/Library/Presentation/PopupErrorInformer.cs new file mode 100644 index 0000000..4f2f54f --- /dev/null +++ b/Library/Presentation/PopupErrorInformer.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Presentation +{ + internal class PopupErrorInformer : IErrorInformer + { + private string _recentMessage; + + public PopupErrorInformer() + { + _recentMessage = string.Empty; + } + + public void InformError(string message) + { + _recentMessage = message; + + MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + + public void InformSuccess(string message) + { + _recentMessage = message; + + MessageBox.Show(message, "Success", MessageBoxButton.OK, MessageBoxImage.Information); + } + + public string GetRecentMessage() + { + return _recentMessage; + } + } +} diff --git a/Library/Presentation/Presentation.csproj b/Library/Presentation/Presentation.csproj new file mode 100644 index 0000000..b2d6cca --- /dev/null +++ b/Library/Presentation/Presentation.csproj @@ -0,0 +1,23 @@ + + + + WinExe + net6.0-windows + enable + enable + true + + + + + + + + + + + + + + + diff --git a/Library/Presentation/View/Event/EventDetailView.xaml b/Library/Presentation/View/Event/EventDetailView.xaml new file mode 100644 index 0000000..c9ba31a --- /dev/null +++ b/Library/Presentation/View/Event/EventDetailView.xaml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + +