From b0e3fcc92d2e040cba65833a19f252f4d9b775ff Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Sun, 29 Oct 2023 22:26:23 +0100 Subject: [PATCH 01/56] remplacement des daos par des classes temporaires --- .../Couche M\303\251tier.csproj" | 1 + .../Manager/AcompteManager.cs" | 4 +- .../Manager/CategoryManager.cs" | 3 +- .../Manager/ProductManager.cs" | 3 +- .../Manager/StatAcompteManager.cs" | 1 + .../Manager/StatProduitManager.cs" | 1 + .../Manager/UserManager.cs" | 3 +- Couche IHM/GalliumPlus.sln | 6 +++ Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs | 12 ++++++ Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs | 12 ++++++ Couche IHM/GalliumPlusApi/Dao/ProductDao.cs | 12 ++++++ Couche IHM/GalliumPlusApi/Dao/UserDao.cs | 12 ++++++ .../GalliumPlusApi/GalliumPlusApi.csproj | 13 +++++++ .../PlaceholderDao/PlaceholderAcompteDao.cs | 28 ++++++++++++++ .../PlaceholderDao/PlaceholderCategoryDao.cs | 28 ++++++++++++++ .../PlaceholderDao/PlaceholderProductDao.cs | 28 ++++++++++++++ .../PlaceholderDao/PlaceholderUserDao.cs | 38 +++++++++++++++++++ 17 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/ProductDao.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/UserDao.cs create mode 100644 Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj create mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs create mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs create mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs create mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs diff --git "a/Couche IHM/Couche M\303\251tier/Couche M\303\251tier.csproj" "b/Couche IHM/Couche M\303\251tier/Couche M\303\251tier.csproj" index a947149..3c57635 100644 --- "a/Couche IHM/Couche M\303\251tier/Couche M\303\251tier.csproj" +++ "b/Couche IHM/Couche M\303\251tier/Couche M\303\251tier.csproj" @@ -14,6 +14,7 @@ + diff --git "a/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" index ab9ee39..7c5c431 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" @@ -1,5 +1,5 @@  -using Couche_Data.Dao; +using GalliumPlusApi.PlaceholderDao; using Couche_Data.Interfaces; using Modeles; @@ -25,7 +25,7 @@ public class AcompteManager /// public AcompteManager() { - this.adhérentDao = new AcompteDAO(); + this.adhérentDao = new PlaceholderAcompteDao(); // Récupération des adhérents adhérents = adhérentDao.GetAdhérents(); diff --git "a/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" index 9451f7e..642941b 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" @@ -1,6 +1,7 @@  using Couche_Data.Dao; using Couche_Data.Interfaces; +using GalliumPlusApi.PlaceholderDao; using Modeles; namespace Couche_Métier.Manager @@ -29,7 +30,7 @@ public class CategoryManager /// public CategoryManager() { - this.iCategory = new CategoryDAO(); + this.iCategory = new PlaceholderCategoryDao(); categories = this.iCategory.ListALlCategory(); } #endregion diff --git "a/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" index 3b4d749..62a461e 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" @@ -1,6 +1,7 @@  using Couche_Data.Dao; using Couche_Data.Interfaces; +using GalliumPlusApi.PlaceholderDao; using Modeles; @@ -29,7 +30,7 @@ public class ProductManager /// public ProductManager() { - this.productDAO = new ProductDAO(); + this.productDAO = new PlaceholderProductDao(); this.products = new List(this.productDAO.GetProducts()); } #endregion diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" index 6fd0a61..767335c 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" @@ -25,6 +25,7 @@ public class StatAcompteManager public StatAcompteManager() { dao = new StatAcompteDAO(); + this.statAcompteList = new List(); Task.Run(() => this.statAcompteList = dao.GetStat()); } diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" index ee1155e..ba083dd 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" @@ -25,6 +25,7 @@ public class StatProduitManager public StatProduitManager() { dao = new StatProduitDAO(); + statProduitList = new(); Task.Run(()=> statProduitList = dao.GetStat()); } #endregion diff --git "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" index a4217a8..8d2200f 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" @@ -2,6 +2,7 @@ using Couche_Data.Dao; using Couche_Data.Interfaces; using Couche_Métier.Utilitaire; +using GalliumPlusApi.PlaceholderDao; using Modeles; @@ -35,7 +36,7 @@ public class UserManager /// public UserManager() { - this.userDao = new UserDAO(); + this.userDao = new PlaceholderUserDao(); this.comptes = this.userDao.GetComptes(); this.roles = this.userDao.GetRoles(); } diff --git a/Couche IHM/GalliumPlus.sln b/Couche IHM/GalliumPlus.sln index 19291f6..e6bb851 100644 --- a/Couche IHM/GalliumPlus.sln +++ b/Couche IHM/GalliumPlus.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Couche Data", "Couche Data\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modeles", "Modeles\Modeles.csproj", "{2DB5D1B3-23F7-4588-AF56-DF548D681ED9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GalliumPlusApi", "GalliumPlusApi\GalliumPlusApi.csproj", "{B71AFCAA-E57B-45D9-989B-6C9A01F62E95}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {2DB5D1B3-23F7-4588-AF56-DF548D681ED9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2DB5D1B3-23F7-4588-AF56-DF548D681ED9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2DB5D1B3-23F7-4588-AF56-DF548D681ED9}.Release|Any CPU.Build.0 = Release|Any CPU + {B71AFCAA-E57B-45D9-989B-6C9A01F62E95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B71AFCAA-E57B-45D9-989B-6C9A01F62E95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B71AFCAA-E57B-45D9-989B-6C9A01F62E95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B71AFCAA-E57B-45D9-989B-6C9A01F62E95}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs new file mode 100644 index 0000000..f9b8bd8 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.Dao +{ + internal class AcompteDao + { + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs new file mode 100644 index 0000000..135b16e --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.Dao +{ + internal class CategoryDao + { + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs new file mode 100644 index 0000000..dea931c --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.Dao +{ + internal class ProductDao + { + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs new file mode 100644 index 0000000..6fd789e --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.Dao +{ + internal class UserDao + { + } +} diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj b/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj new file mode 100644 index 0000000..1f0911a --- /dev/null +++ b/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj @@ -0,0 +1,13 @@ + + + + net6.0-windows + enable + enable + + + + + + + diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs new file mode 100644 index 0000000..152faeb --- /dev/null +++ b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs @@ -0,0 +1,28 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.PlaceholderDao +{ + public class PlaceholderAcompteDao : IAcompteDao + { + public void CreateAdhérent(Acompte adhérent) + { + + } + + public List GetAdhérents() + { + return new List(); + } + + public void RemoveAdhérent(Acompte adhérent) + { + + } + + public void UpdateAdhérent(Acompte adhérent) + { + + } + } +} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs new file mode 100644 index 0000000..6e76adb --- /dev/null +++ b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs @@ -0,0 +1,28 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.PlaceholderDao +{ + public class PlaceholderCategoryDao : ICategoryDao + { + public void CreateCategory(Category cat) + { + + } + + public void DeleteCategory(Category cat) + { + + } + + public List ListALlCategory() + { + return new List(); + } + + public void UpdateCategory(Category category) + { + + } + } +} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs new file mode 100644 index 0000000..0d9b6d8 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs @@ -0,0 +1,28 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.PlaceholderDao +{ + public class PlaceholderProductDao : IProductDAO + { + public void CreateProduct(Product product) + { + + } + + public List GetProducts() + { + return new List(); + } + + public void RemoveProduct(Product product) + { + + } + + public void UpdateProduct(Product product) + { + + } + } +} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs new file mode 100644 index 0000000..1956e3a --- /dev/null +++ b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs @@ -0,0 +1,38 @@ +using Couche_Data.Interfaces; +using Modeles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.PlaceholderDao +{ + public class PlaceholderUserDao : IUserDAO + { + public void CreateCompte(User compte) + { + + } + + public List GetComptes() + { + return new List(); + } + + public List GetRoles() + { + return new List(); + } + + public void RemoveCompte(User compte) + { + + } + + public void UpdateCompte(User compte) + { + + } + } +} From 1f359f61d84e7140d9967a0611924861cc404ca9 Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Mon, 30 Oct 2023 09:39:24 +0100 Subject: [PATCH 02/56] Connexion --- .../VueModeles/MainWindowViewModel.cs | 2 - .../Couche IHM/VueModeles/UserViewModel.cs | 4 +- .../Manager/ProductManager.cs" | 5 +- .../Manager/UserManager.cs" | 13 +- Couche IHM/GalliumPlusApi/ApiConfig.cs | 32 ++++ Couche IHM/GalliumPlusApi/Dao/ProductDao.cs | 28 +++- Couche IHM/GalliumPlusApi/Dao/SessionDao.cs | 31 ++++ Couche IHM/GalliumPlusApi/Dao/UserDao.cs | 33 +++- .../GalliumPlusApi/Dto/CategoryDetails.cs | 32 ++++ .../GalliumPlusApi/Dto/ClientDetails.cs | 142 ++++++++++++++++++ Couche IHM/GalliumPlusApi/Dto/LoggedIn.cs | 18 +++ Couche IHM/GalliumPlusApi/Dto/Mapper.cs | 20 +++ .../GalliumPlusApi/Dto/OrderItemSummary.cs | 34 +++++ Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs | 83 ++++++++++ .../Dto/PasswordModification.cs | 21 +++ .../GalliumPlusApi/Dto/ProductDetails.cs | 70 +++++++++ .../GalliumPlusApi/Dto/ProductSummary.cs | 71 +++++++++ Couche IHM/GalliumPlusApi/Dto/RoleDetails.cs | 26 ++++ Couche IHM/GalliumPlusApi/Dto/UserDetails.cs | 43 ++++++ .../GalliumPlusApi/Dto/UserIdRepository.cs | 60 ++++++++ Couche IHM/GalliumPlusApi/Dto/UserSummary.cs | 79 ++++++++++ .../Exceptions/ExceptionFactory.cs | 19 +++ .../Exceptions/GalliumPlusHttpException.cs | 9 ++ .../Exceptions/UnauthenticatedException.cs | 7 + .../GalliumPlusApi/GalliumPlusApi.csproj | 1 + .../GalliumPlusApi/GalliumPlusHttpClient.cs | 50 ++++++ 26 files changed, 906 insertions(+), 27 deletions(-) create mode 100644 Couche IHM/GalliumPlusApi/ApiConfig.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/SessionDao.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/LoggedIn.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/Mapper.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/PasswordModification.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/RoleDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/UserDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/UserSummary.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/GalliumPlusHttpException.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs create mode 100644 Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs diff --git a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs index 9cf2387..8266a60 100644 --- a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs @@ -159,8 +159,6 @@ private MainWindowViewModel() // Initialisation des events this.ChangeFrame = new RelayCommand(fram => this.Frame = (Frame)fram); - } - } } diff --git a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs index 35ebbdf..a242ab2 100644 --- a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs @@ -109,7 +109,7 @@ public bool CanSeeCompteBool { get { - return (role.Name == "Administrateur"); + return (role?.Name == "Administrateur"); } } @@ -123,7 +123,7 @@ public double CanSeeCompte get { double d = 0.5; - if (role.Name == "Administrateur") + if (role?.Name == "Administrateur") { d = 1; } diff --git "a/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" index 62a461e..0d30a90 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/ProductManager.cs" @@ -1,7 +1,6 @@  -using Couche_Data.Dao; using Couche_Data.Interfaces; -using GalliumPlusApi.PlaceholderDao; +using GalliumPlusApi.Dao; using Modeles; @@ -30,7 +29,7 @@ public class ProductManager /// public ProductManager() { - this.productDAO = new PlaceholderProductDao(); + this.productDAO = new ProductDao(); this.products = new List(this.productDAO.GetProducts()); } #endregion diff --git "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" index 8d2200f..cad2057 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" @@ -2,6 +2,8 @@ using Couche_Data.Dao; using Couche_Data.Interfaces; using Couche_Métier.Utilitaire; +using GalliumPlusApi.Dao; +using GalliumPlusApi.Dto; using GalliumPlusApi.PlaceholderDao; using Modeles; @@ -104,14 +106,9 @@ public void UpdateCompte(User compte) /// public User? ConnectCompte(string identifiant,string password) { - User? user = this.comptes.Find(x => x.Mail == identifiant); - User? userFinal = null; - if (user != null &&CryptString.Verify(password, user.HashedPassword)) - { - userFinal = user; - } - - return userFinal; + SessionDao dao = new(); + + return dao.LogIn(identifiant, password); } #endregion } diff --git a/Couche IHM/GalliumPlusApi/ApiConfig.cs b/Couche IHM/GalliumPlusApi/ApiConfig.cs new file mode 100644 index 0000000..52cfd40 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/ApiConfig.cs @@ -0,0 +1,32 @@ +namespace GalliumPlusApi +{ + internal class ApiConfig + { + private static ApiConfig? current; + + public static ApiConfig Current + { + get + { + if (current == null) + { + current = new(); + } + return current; + } + } + + private string apiKey; + private string host; + + public string ApiKey => apiKey; + + public string Host => host; + + private ApiConfig() + { + apiKey = "test-api-key-normal"; + host = "localhost:5443"; + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs index dea931c..48da904 100644 --- a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs @@ -1,12 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Couche_Data.Interfaces; +using Modeles; namespace GalliumPlusApi.Dao { - internal class ProductDao + public class ProductDao : IProductDAO { + public void CreateProduct(Product product) + { + throw new NotImplementedException(); + } + + public List GetProducts() + { + throw new NotImplementedException(); + } + + public void RemoveProduct(Product product) + { + throw new NotImplementedException(); + } + + public void UpdateProduct(Product product) + { + throw new NotImplementedException(); + } } } diff --git a/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs b/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs new file mode 100644 index 0000000..0cfd881 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs @@ -0,0 +1,31 @@ +using GalliumPlusApi.Dto; +using GalliumPlusApi.Exceptions; +using Modeles; +using System.Text.Json; + +namespace GalliumPlusApi.Dao +{ + public class SessionDao + { + private UserDetails.Mapper detailsMapper = new(); + + public User? LogIn(string username, string password) + { + using var client = new GalliumPlusHttpClient(); + client.JsonOptions.PropertyNamingPolicy = null; // pas de casse chameau + + try + { + var loggedIn = client.Post("v1/login", new { Username = username, Password = password }); + + if (loggedIn.User == null) return null; + + return this.detailsMapper.ToModel(loggedIn.User); + } + catch (UnauthenticatedException) + { + return null; + } + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs index 6fd789e..f6732c9 100644 --- a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs @@ -1,12 +1,33 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Couche_Data.Interfaces; +using Modeles; namespace GalliumPlusApi.Dao { - internal class UserDao + public class UserDao : IUserDAO { + public void CreateCompte(User compte) + { + throw new NotImplementedException(); + } + + public List GetComptes() + { + throw new NotImplementedException(); + } + + public List GetRoles() + { + throw new NotImplementedException(); + } + + public void RemoveCompte(User compte) + { + throw new NotImplementedException(); + } + + public void UpdateCompte(User compte) + { + throw new NotImplementedException(); + } } } diff --git a/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs b/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs new file mode 100644 index 0000000..29dd88c --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs @@ -0,0 +1,32 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Stocks; +using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class CategoryDetails + { + public int Id { get; set; } + [Required] public string Name { get; set; } + + public CategoryDetails() + { + this.Id = -1; + this.Name = String.Empty; + } + + public class Mapper : Mapper + { + public override CategoryDetails FromModel(Category model) + { + return new CategoryDetails { Id = model.Id, Name = model.Name }; + } + + public override Category ToModel(CategoryDetails dto) + { + return new Category(dto.Id, dto.Name); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs b/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs new file mode 100644 index 0000000..a32e410 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs @@ -0,0 +1,142 @@ +/*using GalliumPlus.WebApi.Core.Applications; +using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Exceptions; +using GalliumPlus.WebApi.Core.Users; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace GalliumPlus.WebApi.Dto +{ + public class ClientDetails + { + public enum ClientType { CLIENT, BOT_CLIENT, SSO_CLIENT } + + public ClientType? Type { get; set; } + public int Id { get; set; } + public string? ApiKey { get; set; } + [Required] public string Name { get; set; } + [Required] public uint? PermissionsGranted { get; set; } + [Required] public bool? IsEnabled { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? PermissionsRevoked { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? UsesApi { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? RedirectUrl { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? LogoUrl { get; set; } + + public ClientDetails() + { + this.Id = -1; + this.Name = String.Empty; + } + + public class Mapper : Mapper + { + public override ClientDetails FromModel(Client model) + { + ClientDetails dto = new() + { + Id = model.Id, + ApiKey = model.ApiKey, + Name = model.Name, + PermissionsGranted = (uint)model.Granted, + IsEnabled = model.IsEnabled, + }; + + if (model is BotClient) + { + dto.Type = ClientType.BOT_CLIENT; + } + else + { + dto.PermissionsRevoked = (uint)model.Revoked; + + if (model is SsoClient ssoClient) + { + dto.Type = ClientType.SSO_CLIENT; + dto.RedirectUrl = ssoClient.RedirectUrl; + dto.LogoUrl = ssoClient.LogoUrl; + dto.UsesApi = ssoClient.UsesApi; + } + else + { + dto.Type = ClientType.CLIENT; + } + } + + return dto; + } + + private static Exception MissingField() + { + return new InvalidItemException($"Les informations sur l'application sont incomplètes."); + } + + public override Client ToModel(ClientDetails dto) + { + if (!dto.Type.HasValue) + { + throw MissingField(); + } + + switch (dto.Type.Value) + { + case ClientType.CLIENT: + return new Client( + name: dto.Name, + isEnabled: dto.IsEnabled!.Value, + granted: (Permissions)dto.PermissionsGranted!.Value, + revoked: (Permissions)(dto.PermissionsRevoked ?? throw MissingField()) + ); + + case ClientType.BOT_CLIENT: + return new BotClient( + name: dto.Name, + isEnabled: dto.IsEnabled!.Value, + permissions: (Permissions)dto.PermissionsGranted!.Value + ); + + case ClientType.SSO_CLIENT: + return new SsoClient( + name: dto.Name, + isEnabled: dto.IsEnabled!.Value, + granted: (Permissions)dto.PermissionsGranted!.Value, + revoked: (Permissions)(dto.PermissionsRevoked ?? throw MissingField()), + usesApi: dto.UsesApi ?? throw MissingField(), + redirectUrl: dto.RedirectUrl ?? throw MissingField(), + logoUrl: dto.LogoUrl + ); + + default: + throw new InvalidItemException("Type de client invalide"); + } + } + + public void PatchModel(Client original, ClientDetails patch) + { + original.Name = patch.Name; + original.IsEnabled = patch.IsEnabled!.Value; + original.Granted = (Permissions)patch.PermissionsGranted!.Value; + + if (original is not BotClient) + { + original.Revoked = (Permissions)(patch.PermissionsRevoked ?? throw MissingField()); + + if (original is SsoClient originalSso) + { + originalSso.RedirectUrl = patch.RedirectUrl ?? throw MissingField(); + originalSso.UsesApi = patch.UsesApi ?? throw MissingField(); + originalSso.LogoUrl = patch.LogoUrl; + } + } + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/LoggedIn.cs b/Couche IHM/GalliumPlusApi/Dto/LoggedIn.cs new file mode 100644 index 0000000..b946630 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/LoggedIn.cs @@ -0,0 +1,18 @@ +namespace GalliumPlusApi.Dto +{ + public class LoggedIn + { + public string Token { get; set; } + public DateTime Expiration { get; set; } + public UserDetails? User { get; set; } + public uint Permissions { get; set; } + + public LoggedIn() + { + Token = ""; + Expiration = new(0); + User = new(); + Permissions = 0; + } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/Mapper.cs b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs new file mode 100644 index 0000000..96823dc --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs @@ -0,0 +1,20 @@ +namespace GalliumPlusApi.Dto +{ + public abstract class Mapper + { + public virtual TModel ToModel(TDto dto) + { + throw new InvalidOperationException("Ce DTO ne doit pas entrer !! >:("); + } + + public IEnumerable toModel(IEnumerable dtos) + { + foreach (TDto dto in dtos) yield return ToModel(dto); + } + + public virtual TDto FromModel(TModel model) + { + throw new InvalidOperationException("Ce DTO ne doit pas sortir !! >:("); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs b/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs new file mode 100644 index 0000000..50da478 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs @@ -0,0 +1,34 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Orders; +using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class OrderItemSummary + { + [Required] public int? Product { get; set; } + [Required] public int? Quantity { get; set; } + + public class Mapper : Mapper + { + private IProductDao productDao; + + public Mapper(IProductDao productDao) + { + this.productDao = productDao; + } + + public override OrderItemSummary FromModel(OrderItem model) + { + // ne sort jamais du serveur ! + throw new NotImplementedException(); + } + + public override OrderItem ToModel(OrderItemSummary dto) + { + return new OrderItem(this.productDao.Read(dto.Product!.Value), dto.Quantity!.Value); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs b/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs new file mode 100644 index 0000000..056f138 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs @@ -0,0 +1,83 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Exceptions; +using GalliumPlus.WebApi.Core.Orders; +using GalliumPlus.WebApi.Core.Users; +using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class OrderSummary + { + [Required] public string PaymentMethod { get; set; } + public string? Customer { get; set; } + [Required] public List? Items { get; set; } + + public OrderSummary() + { + PaymentMethod = String.Empty; + Items = null; + } + + public class Mapper : Mapper + { + private OrderItemSummary.Mapper orderItemMapper; + private IUserDao userDao; + + public Mapper(IUserDao userDao, IProductDao productDao) + { + this.userDao = userDao; + this.orderItemMapper = new(productDao); + } + + public override OrderSummary FromModel(Order model) + { + // ne sort jamais du serveur ! + throw new NotImplementedException(); + } + + public override Order ToModel(OrderSummary dto) + { + PaymentMethodFactory factory = new(this.userDao); + + User? customer; + if (dto.Customer == null) + { + customer = null; + } + else if (dto.Customer == Order.ANONYMOUS_MEMBER_ID) + { + customer = BuildAnonymousMember(); + } + else + { + try + { + customer = this.userDao.Read(dto.Customer); + } + catch (ItemNotFoundException) + { + throw new InvalidItemException($"L'utilisateur « {dto.Customer} » n'existe pas"); + } + } + + return new Order( + factory.Create(dto.PaymentMethod, dto.Customer), + dto.Items!.Select(saleItemDto => this.orderItemMapper.ToModel(saleItemDto)), + customer + ); + } + + private static User BuildAnonymousMember() + { + return new User( + "anonymousmember00000000000", // pas possible d'être rentré en BDD + new UserIdentity("Anonyme", "", "", ""), + new Role(-1, "Membre anonyme", Permissions.NONE), + 0.00m, + false + ); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/PasswordModification.cs b/Couche IHM/GalliumPlusApi/Dto/PasswordModification.cs new file mode 100644 index 0000000..69863d2 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/PasswordModification.cs @@ -0,0 +1,21 @@ +/*using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class PasswordModification + { + public string? CurrentPassword { get; } + + public string? ResetToken { get; } + + [Required] public string NewPassword { get; } + + public PasswordModification(string newPassword, string? currentPassword, string? resetToken) + { + this.CurrentPassword = currentPassword; + this.ResetToken = resetToken; + this.NewPassword = newPassword; + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs new file mode 100644 index 0000000..e1a8e30 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs @@ -0,0 +1,70 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Stocks; + +namespace GalliumPlus.WebApi.Dto +{ + public class ProductDetails + { + public int Id { get; set; } + public string Name { get; set; } + public int Stock { get; set; } + public decimal NonMemberPrice { get; set; } + public decimal MemberPrice { get; set; } + public Availability Availability { get; set; } + public bool Available { get; set; } + public CategoryDetails Category { get; set; } + + public ProductDetails( + int id, + string name, + int stock, + decimal nonMemberPrice, + decimal memberPrice, + Availability availability, + bool available, + CategoryDetails category) + { + this.Id = id; + this.Name = name; + this.Stock = stock; + this.NonMemberPrice = nonMemberPrice; + this.MemberPrice = memberPrice; + this.Availability = availability; + this.Available = available; + this.Category = category; + } + + public class Mapper : Mapper + { + private CategoryDetails.Mapper categoryMapper = new(); + + public override ProductDetails FromModel(Product model) + { + return new ProductDetails( + model.Id, + model.Name, + model.Stock, + model.NonMemberPrice, + model.MemberPrice, + model.Availability, + model.Available, + this.categoryMapper.FromModel(model.Category) + ); + } + + public override Product ToModel(ProductDetails dto) + { + return new Product( + dto.Id, + dto.Name, + dto.Stock, + dto.NonMemberPrice, + dto.MemberPrice, + dto.Availability, + this.categoryMapper.ToModel(dto.Category) + ); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs new file mode 100644 index 0000000..3904c3b --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs @@ -0,0 +1,71 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Exceptions; +using GalliumPlus.WebApi.Core.Stocks; +using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class ProductSummary + { + public int Id { get; set; } + [Required] public string Name { get; set; } + [Required] public int? Stock { get; set; } + [Required] public decimal? NonMemberPrice { get; set; } + [Required] public decimal? MemberPrice { get; set; } + [Required] public Availability? Availability { get; set; } + [Required] public int? Category { get; set; } + + public ProductSummary() + { + this.Id = -1; + this.Name = string.Empty; + } + + public class Mapper : Mapper + { + private ICategoryDao categoryDao; + + public Mapper(ICategoryDao categoryDao) + { + this.categoryDao = categoryDao; + } + + public override ProductSummary FromModel(Product model) + { + return new ProductSummary + { + Id = model.Id, + Name = model.Name, + Stock = model.Stock, + NonMemberPrice = model.NonMemberPrice, + MemberPrice = model.MemberPrice, + Availability = model.Availability, + Category = model.Category.Id + }; + } + + public override Product ToModel(ProductSummary dto) + { + Category category; + try + { + category = this.categoryDao.Read(dto.Category!.Value); + } + catch (ItemNotFoundException) + { + throw new InvalidItemException("La catégorie associée n'existe pas"); + } + + return new Product( + dto.Id, dto.Name, + dto.Stock!.Value, + dto.NonMemberPrice!.Value, + dto.MemberPrice!.Value, + dto.Availability!.Value, + category + ); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/RoleDetails.cs b/Couche IHM/GalliumPlusApi/Dto/RoleDetails.cs new file mode 100644 index 0000000..dd526bc --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/RoleDetails.cs @@ -0,0 +1,26 @@ +using Modeles; + +namespace GalliumPlusApi.Dto +{ + public class RoleDetails + { + public int Id { get; set; } + public string Name { get; set; } + public uint Permissions { get; set; } + + public RoleDetails() + { + this.Id = -1; + this.Name = String.Empty; + this.Permissions = 0; + } + + public class Mapper : Mapper + { + public override Role ToModel(RoleDetails dto) + { + return new Role(dto.Id, dto.Name); + } + } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs new file mode 100644 index 0000000..655083c --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs @@ -0,0 +1,43 @@ +using Modeles; + +namespace GalliumPlusApi.Dto +{ + public class UserDetails + { + public string Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public RoleDetails Role { get; set; } + public string Year { get; set; } + public decimal? Deposit { get; set; } + public bool IsMember { get; set; } + + public UserDetails() + { + Id = ""; + FirstName = ""; + LastName = ""; + Email = ""; + Role = new(); + Year = ""; + Deposit = null; + IsMember = false; + } + + public class Mapper : Mapper + { + public override User ToModel(UserDetails details) + { + return new User( + UserIdRepository.Current.GetIdFor(details.Id), + details.LastName, + details.FirstName, + details.Email, + "", + details.Role.Id + ); + } + } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs b/Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs new file mode 100644 index 0000000..40a7e8e --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GalliumPlusApi.Dto +{ + internal class UserIdRepository + { + private static UserIdRepository? current; + + public static UserIdRepository Current + { + get + { + if (current == null) + { + current = new UserIdRepository(); + } + return current; + } + } + + private Dictionary ids; + private int nextAutoId; + + private UserIdRepository() + { + ids = new Dictionary(); + nextAutoId = 1; + } + + public int GetIdFor(string username) + { + lock(ids) + { + if (ids.ContainsKey(username)) + { + return ids[username]; + } + else + { + int id = nextAutoId++; + ids[username] = id; + return id; + } + } + } + + public string FindUsernameOf(int numericId) + { + lock(ids) + { + return ids.First(kvp => kvp.Value == numericId).Key; + } + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs new file mode 100644 index 0000000..05e8aad --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs @@ -0,0 +1,79 @@ +/*using GalliumPlus.WebApi.Core.Data; +using GalliumPlus.WebApi.Core.Exceptions; +using GalliumPlus.WebApi.Core.Users; +using System.ComponentModel.DataAnnotations; + +namespace GalliumPlus.WebApi.Dto +{ + public class UserSummary + { + [Required] public string Id { get; set; } + [Required] public string FirstName { get; set; } + [Required] public string LastName { get; set; } + [Required] public string Email { get; set; } + [Required] public int? Role { get; set; } + [Required] public string Year { get; set; } + public decimal? Deposit { get; set; } + [Required] public bool? IsMember { get; set; } + + public UserSummary() + { + this.Id = String.Empty; + this.FirstName = String.Empty; + this.LastName = String.Empty; + this.Email = String.Empty; + this.Role = null; + this.Year = String.Empty; + this.Deposit = null; + this.IsMember = null; + } + + public class Mapper : Mapper + { + private IRoleDao roleDao; + + public Mapper(IRoleDao roleDao) + { + this.roleDao = roleDao; + } + + + public override UserSummary FromModel(User user) + { + return new UserSummary + { + Id = user.Id, + FirstName = user.Identity.FirstName, + LastName = user.Identity.LastName, + Email = user.Identity.Email, + Role = user.Role.Id, + Year = user.Identity.Year, + Deposit = user.Deposit, + IsMember = user.IsMember + }; + } + + public override User ToModel(UserSummary summary) + { + Role role; + try + { + role = this.roleDao.Read(summary.Role!.Value); + } + catch (ItemNotFoundException) + { + throw new InvalidItemException("Le rôle associé n'existe pas"); + } + + return new User( + summary.Id!, + new UserIdentity(summary.FirstName!, summary.LastName!, summary.Email!, summary.Year!), + role, + summary.Deposit!.Value, + summary.IsMember!.Value + ); + } + } + } +} +*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs new file mode 100644 index 0000000..e25b4a2 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs @@ -0,0 +1,19 @@ +using System.Net; + +namespace GalliumPlusApi.Exceptions +{ + internal static class ExceptionFactory + { + public static void ThrowForStatus(HttpResponseMessage response) + { + if (!response.IsSuccessStatusCode) + { + throw response.StatusCode switch + { + HttpStatusCode.Unauthorized => new UnauthenticatedException(), + _ => new GalliumPlusHttpException($"Erreur HTTP non gérée : {response.StatusCode} {response.ReasonPhrase}"), + }; + } + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Exceptions/GalliumPlusHttpException.cs b/Couche IHM/GalliumPlusApi/Exceptions/GalliumPlusHttpException.cs new file mode 100644 index 0000000..340a0a7 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/GalliumPlusHttpException.cs @@ -0,0 +1,9 @@ +namespace GalliumPlusApi.Exceptions +{ + public class GalliumPlusHttpException : Exception + { + public GalliumPlusHttpException() : base() { } + + public GalliumPlusHttpException(string message) : base(message) { } + } +} diff --git a/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs b/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs new file mode 100644 index 0000000..f3f6ad7 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs @@ -0,0 +1,7 @@ +namespace GalliumPlusApi.Exceptions +{ + public class UnauthenticatedException : GalliumPlusHttpException + { + public UnauthenticatedException() : base() { } + } +} diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj b/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj index 1f0911a..2f2fd68 100644 --- a/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj +++ b/Couche IHM/GalliumPlusApi/GalliumPlusApi.csproj @@ -8,6 +8,7 @@ + diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs new file mode 100644 index 0000000..860c4e6 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs @@ -0,0 +1,50 @@ +using GalliumPlusApi.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace GalliumPlusApi +{ + internal class GalliumPlusHttpClient : HttpClient + { + private JsonSerializerOptions jsonOptions; + + public JsonSerializerOptions JsonOptions => jsonOptions; + + public GalliumPlusHttpClient() + { + BaseAddress = new Uri("https://" + ApiConfig.Current.Host); + DefaultRequestHeaders.Add("X-Api-Key", ApiConfig.Current.ApiKey); + jsonOptions = new JsonSerializerOptions(); + } + + private static T WaitForTask(Task task) + { + task.Wait(); + + if (task.IsFaulted) + { + throw task.Exception ?? new Exception("Unknown error in task"); + } + + return task.Result; + } + + public T Post(string resource, object data) + { + var response = WaitForTask(this.PostAsJsonAsync(resource, data, jsonOptions)); + + ExceptionFactory.ThrowForStatus(response); + + return WaitForTask(response.Content.ReadFromJsonAsync(jsonOptions)) + ?? throw new NullReferenceException("Json deserialisation return null"); + } + + // public T Get(string url) + + } +} From daaf7e8e5da0e7e3b7da9529de0ba5637d24e36b Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Mon, 30 Oct 2023 17:52:48 +0100 Subject: [PATCH 03/56] =?UTF-8?q?Lecture=20des=20donn=C3=A9es=20depuis=20l?= =?UTF-8?q?'API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Couche IHM/Couche Data/Dao/LogDAO.cs | 14 +- Couche IHM/Couche Data/Dao/StatAcompteDAO.cs | 7 +- Couche IHM/Couche Data/Dao/StatProduitDAO.cs | 9 +- Couche IHM/Couche Data/Dao/dbsDAO.cs | 2 +- Couche IHM/Couche Data/Interfaces/ILogDAO.cs | 10 ++ .../Couche Data/Interfaces/IStatAcompteDAO.cs | 10 ++ .../Couche Data/Interfaces/IStatProduitDAO.cs | 10 ++ Couche IHM/Couche IHM/ConnexionIHM.xaml.cs | 9 +- .../Couche IHM/VueModeles/UserViewModel.cs | 9 +- .../Manager/AcompteManager.cs" | 7 +- .../Manager/CategoryManager.cs" | 8 +- .../Manager/LogManager.cs" | 3 +- .../Manager/StatAcompteManager.cs" | 6 +- .../Manager/StatProduitManager.cs" | 6 +- .../Manager/UserManager.cs" | 24 ++- .../CompatibilityHelpers/Format.cs | 11 ++ .../UserIdRepository.cs | 6 +- Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs | 45 ++++- Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs | 45 ++++- Couche IHM/GalliumPlusApi/Dao/LogDAO.cs | 18 ++ Couche IHM/GalliumPlusApi/Dao/ProductDao.cs | 19 ++- Couche IHM/GalliumPlusApi/Dao/SessionDao.cs | 9 +- .../GalliumPlusApi/Dao/StatAcompteDAO.cs | 18 ++ .../GalliumPlusApi/Dao/StatProduitDAO.cs | 18 ++ Couche IHM/GalliumPlusApi/Dao/UserDao.cs | 39 ++++- .../GalliumPlusApi/Dto/CategoryDetails.cs | 23 +-- .../GalliumPlusApi/Dto/ClientDetails.cs | 142 --------------- Couche IHM/GalliumPlusApi/Dto/Mapper.cs | 2 +- .../GalliumPlusApi/Dto/ProductSummary.cs | 74 +++----- Couche IHM/GalliumPlusApi/Dto/UserDetails.cs | 3 +- Couche IHM/GalliumPlusApi/Dto/UserSummary.cs | 161 ++++++++++++------ .../Exceptions/ExceptionFactory.cs | 2 +- .../GalliumPlusApi/GalliumPlusHttpClient.cs | 20 ++- .../ModelDecorators/DecoratedAcompte.cs | 31 ++++ .../ModelDecorators/DecoratedUser.cs | 35 ++++ .../PlaceholderDao/PlaceholderAcompteDao.cs | 28 --- .../PlaceholderDao/PlaceholderCategoryDao.cs | 28 --- .../PlaceholderDao/PlaceholderProductDao.cs | 28 --- .../PlaceholderDao/PlaceholderUserDao.cs | 38 ----- Couche IHM/GalliumPlusApi/SessionStorage.cs | 48 ++++++ 40 files changed, 564 insertions(+), 461 deletions(-) create mode 100644 Couche IHM/Couche Data/Interfaces/ILogDAO.cs create mode 100644 Couche IHM/Couche Data/Interfaces/IStatAcompteDAO.cs create mode 100644 Couche IHM/Couche Data/Interfaces/IStatProduitDAO.cs create mode 100644 Couche IHM/GalliumPlusApi/CompatibilityHelpers/Format.cs rename Couche IHM/GalliumPlusApi/{Dto => CompatibilityHelpers}/UserIdRepository.cs (93%) create mode 100644 Couche IHM/GalliumPlusApi/Dao/LogDAO.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs create mode 100644 Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs delete mode 100644 Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs create mode 100644 Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedAcompte.cs create mode 100644 Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedUser.cs delete mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs delete mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs delete mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs delete mode 100644 Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs create mode 100644 Couche IHM/GalliumPlusApi/SessionStorage.cs diff --git a/Couche IHM/Couche Data/Dao/LogDAO.cs b/Couche IHM/Couche Data/Dao/LogDAO.cs index 05df1bd..c27c1f6 100644 --- a/Couche IHM/Couche Data/Dao/LogDAO.cs +++ b/Couche IHM/Couche Data/Dao/LogDAO.cs @@ -1,9 +1,10 @@ -using Modeles; +using Couche_Data.Interfaces; +using Modeles; using MySql.Data.MySqlClient; namespace Couche_Data.Dao { - public class LogDAO + public class LogDAO : ILogDAO { public void CreateLog(Log log) @@ -27,10 +28,10 @@ public void CreateLog(Log log) } - public List GetLogs(int mois,int annee) + public List GetLogs(int mois, int annee) { //Connection - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_gallium", "none"); + string connString = "nope"; MySqlConnection sql = new MySqlConnection(connString); sql.Open(); //Requette SQL @@ -50,10 +51,5 @@ public List GetLogs(int mois,int annee) sql.Close(); return logs; } - - - - - } } diff --git a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs index 73749fa..909e50c 100644 --- a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs @@ -1,16 +1,17 @@ -using Modeles; +using Couche_Data.Interfaces; +using Modeles; using MySql.Data.MySqlClient; namespace Couche_Data.Dao { - public class StatAcompteDAO + public class StatAcompteDAO : IStatAcompteDAO { public List GetStat() { //Connection - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); + string connString ="nope"; MySqlConnection sql = new MySqlConnection(connString); sql.Open(); diff --git a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs index dd329d0..0e3bbca 100644 --- a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs @@ -1,16 +1,17 @@ -using Modeles; +using Couche_Data.Interfaces; +using Modeles; using MySql.Data.MySqlClient; namespace Couche_Data.Dao { - public class StatProduitDAO + public class StatProduitDAO : IStatProduitDAO { public List GetStat() { //Connection - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); + string connString = "nope"; MySqlConnection sql = new MySqlConnection(connString); sql.Open(); @@ -51,7 +52,7 @@ public void CreateStat(StatProduit stat) cmd.ExecuteNonQuery(); sql.Close(); - + } } } diff --git a/Couche IHM/Couche Data/Dao/dbsDAO.cs b/Couche IHM/Couche Data/Dao/dbsDAO.cs index 4664d20..9d0884c 100644 --- a/Couche IHM/Couche Data/Dao/dbsDAO.cs +++ b/Couche IHM/Couche Data/Dao/dbsDAO.cs @@ -80,7 +80,7 @@ public object DatabaseLock /// private void ConnexionToBdd() { - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); + string connString = "nope"; this.sql = new MySqlConnection(connString); } diff --git a/Couche IHM/Couche Data/Interfaces/ILogDAO.cs b/Couche IHM/Couche Data/Interfaces/ILogDAO.cs new file mode 100644 index 0000000..6391570 --- /dev/null +++ b/Couche IHM/Couche Data/Interfaces/ILogDAO.cs @@ -0,0 +1,10 @@ +using Modeles; + +namespace Couche_Data.Interfaces +{ + public interface ILogDAO + { + void CreateLog(Log log); + List GetLogs(int mois, int annee); + } +} \ No newline at end of file diff --git a/Couche IHM/Couche Data/Interfaces/IStatAcompteDAO.cs b/Couche IHM/Couche Data/Interfaces/IStatAcompteDAO.cs new file mode 100644 index 0000000..725018f --- /dev/null +++ b/Couche IHM/Couche Data/Interfaces/IStatAcompteDAO.cs @@ -0,0 +1,10 @@ +using Modeles; + +namespace Couche_Data.Interfaces +{ + public interface IStatAcompteDAO + { + void CreateStat(StatAcompte stat); + List GetStat(); + } +} \ No newline at end of file diff --git a/Couche IHM/Couche Data/Interfaces/IStatProduitDAO.cs b/Couche IHM/Couche Data/Interfaces/IStatProduitDAO.cs new file mode 100644 index 0000000..a1664c8 --- /dev/null +++ b/Couche IHM/Couche Data/Interfaces/IStatProduitDAO.cs @@ -0,0 +1,10 @@ +using Modeles; + +namespace Couche_Data.Interfaces +{ + public interface IStatProduitDAO + { + void CreateStat(StatProduit stat); + List GetStat(); + } +} \ No newline at end of file diff --git a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs index 58eb900..e82b7e3 100644 --- a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs +++ b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs @@ -29,6 +29,9 @@ public ConnexionIHM() DataContext = this; this.messageQueue = new SnackbarMessageQueue(new TimeSpan(0, 0, 2)); ImageManager.VerifyFiles(); + + Identifiant = "eb069420"; + Password = "motdepasse"; } public string Identifiant { get => identifiant; set => identifiant = value; } @@ -50,11 +53,11 @@ private void ConnectToAccount(object sender, RoutedEventArgs e) { try { - userManager = MainWindowViewModel.Instance.UserManager; - logManager = MainWindowViewModel.Instance.LogManager; - User? user = this.userManager.ConnectCompte(identifiant, password); + User? user = UserManager.ConnectCompte(identifiant, password); if (user != null) { + userManager = MainWindowViewModel.Instance.UserManager; + logManager = MainWindowViewModel.Instance.LogManager; Log log = new Log(DateTime.Now, 1, $"Connexion de {user.Prenom} {user.Nom}", $"{user.Prenom} {user.Nom}"); logManager.CreateLog(log); MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); diff --git a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs index a242ab2..7e44baa 100644 --- a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs @@ -109,7 +109,7 @@ public bool CanSeeCompteBool { get { - return (role?.Name == "Administrateur"); + return true; } } @@ -122,12 +122,7 @@ public double CanSeeCompte { get { - double d = 0.5; - if (role?.Name == "Administrateur") - { - d = 1; - } - return d; + return 1; } } diff --git "a/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" index 7c5c431..1ae3e48 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/AcompteManager.cs" @@ -1,6 +1,5 @@ - -using GalliumPlusApi.PlaceholderDao; -using Couche_Data.Interfaces; +using Couche_Data.Interfaces; +using GalliumPlusApi.Dao; using Modeles; namespace Couche_Métier.Manager @@ -25,7 +24,7 @@ public class AcompteManager /// public AcompteManager() { - this.adhérentDao = new PlaceholderAcompteDao(); + this.adhérentDao = new AcompteDao(); // Récupération des adhérents adhérents = adhérentDao.GetAdhérents(); diff --git "a/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" index 642941b..50e6192 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/CategoryManager.cs" @@ -1,7 +1,5 @@ - -using Couche_Data.Dao; -using Couche_Data.Interfaces; -using GalliumPlusApi.PlaceholderDao; +using Couche_Data.Interfaces; +using GalliumPlusApi.Dao; using Modeles; namespace Couche_Métier.Manager @@ -30,7 +28,7 @@ public class CategoryManager /// public CategoryManager() { - this.iCategory = new PlaceholderCategoryDao(); + this.iCategory = new CategoryDao(); categories = this.iCategory.ListALlCategory(); } #endregion diff --git "a/Couche IHM/Couche M\303\251tier/Manager/LogManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/LogManager.cs" index 866f22f..a94f80a 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/LogManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/LogManager.cs" @@ -1,5 +1,4 @@ -using Couche_Data; -using Couche_Data.Dao; +using GalliumPlusApi.Dao; using Modeles; diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" index 767335c..2ad9a9a 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" @@ -1,5 +1,7 @@ using Couche_Data; using Couche_Data.Dao; +using Couche_Data.Interfaces; +using GalliumPlusApi.Dao; using Modeles; namespace Couche_Métier.Manager @@ -10,7 +12,7 @@ public class StatAcompteManager /// /// Dao permettant de gérer les données des stats d'acompte /// - private StatAcompteDAO dao; + private IStatAcompteDAO dao; /// /// Liste des stats d'acompte @@ -24,7 +26,7 @@ public class StatAcompteManager /// public StatAcompteManager() { - dao = new StatAcompteDAO(); + dao = new GalliumPlusApi.Dao.StatAcompteDAO(); this.statAcompteList = new List(); Task.Run(() => this.statAcompteList = dao.GetStat()); diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" index ba083dd..dff7c67 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" @@ -1,5 +1,5 @@ -using Couche_Data; -using Couche_Data.Dao; +using GalliumPlusApi.Dao; +using Couche_Data.Interfaces; using Modeles; namespace Couche_Métier.Manager @@ -10,7 +10,7 @@ public class StatProduitManager /// /// Dao permettant de gérer les données des stats produits /// - private StatProduitDAO dao; + private IStatProduitDAO dao; /// /// Liste des stats des produits diff --git "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" index cad2057..c50236b 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/UserManager.cs" @@ -1,10 +1,5 @@ - -using Couche_Data.Dao; -using Couche_Data.Interfaces; -using Couche_Métier.Utilitaire; +using Couche_Data.Interfaces; using GalliumPlusApi.Dao; -using GalliumPlusApi.Dto; -using GalliumPlusApi.PlaceholderDao; using Modeles; @@ -38,7 +33,7 @@ public class UserManager /// public UserManager() { - this.userDao = new PlaceholderUserDao(); + this.userDao = new UserDao(); this.comptes = this.userDao.GetComptes(); this.roles = this.userDao.GetRoles(); } @@ -104,11 +99,22 @@ public void UpdateCompte(User compte) /// /// /// - public User? ConnectCompte(string identifiant,string password) + public static User? ConnectCompte(string identifiant,string password) { SessionDao dao = new(); - return dao.LogIn(identifiant, password); + var result = dao.LogIn(identifiant, password); + User? user = result?.Item1; + Role? role = result?.Item2; + + if (role?.Name == "Adhérent") + { + return null; + } + else + { + return user; + } } #endregion } diff --git a/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Format.cs b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Format.cs new file mode 100644 index 0000000..8cc1e64 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Format.cs @@ -0,0 +1,11 @@ +namespace GalliumPlusApi.CompatibilityHelpers +{ + internal static class Format + { + public static decimal FloatToMonetary(float value) + { + string roundedRepr = value.ToString("0.00"); + return decimal.Parse(roundedRepr); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/UserIdRepository.cs similarity index 93% rename from Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs rename to Couche IHM/GalliumPlusApi/CompatibilityHelpers/UserIdRepository.cs index 40a7e8e..a34fd67 100644 --- a/Couche IHM/GalliumPlusApi/Dto/UserIdRepository.cs +++ b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/UserIdRepository.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; -namespace GalliumPlusApi.Dto +namespace GalliumPlusApi.CompatibilityHelpers { internal class UserIdRepository { @@ -34,7 +34,7 @@ private UserIdRepository() public int GetIdFor(string username) { - lock(ids) + lock (ids) { if (ids.ContainsKey(username)) { @@ -51,7 +51,7 @@ public int GetIdFor(string username) public string FindUsernameOf(int numericId) { - lock(ids) + lock (ids) { return ids.First(kvp => kvp.Value == numericId).Key; } diff --git a/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs index f9b8bd8..38b01f3 100644 --- a/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs @@ -1,12 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Couche_Data.Interfaces; +using GalliumPlusApi.Dto; +using Modeles; +using System.Diagnostics; namespace GalliumPlusApi.Dao { - internal class AcompteDao + public class AcompteDao : IAcompteDao { + private UserSummary.AcompteMapper mapper = new(); + public void CreateAdhérent(Acompte adhérent) + { + throw new NotImplementedException(); + } + + public List GetAdhérents() + { + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var users = client.Get>("v1/users") + .Where(user => user.Deposit != null); + + return mapper.ToModel(users).ToList(); + } + catch (Exception ex) + { + Debug.WriteLine($"Exception non gérée lors de la récupération des acomptes : {ex}"); + return new List(); + } + } + + public void RemoveAdhérent(Acompte adhérent) + { + throw new NotImplementedException(); + } + + public void UpdateAdhérent(Acompte adhérent) + { + throw new NotImplementedException(); + } } } diff --git a/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs index 135b16e..5c2318f 100644 --- a/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs @@ -1,12 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Couche_Data.Interfaces; +using GalliumPlusApi.Dto; +using Modeles; +using System.Diagnostics; namespace GalliumPlusApi.Dao { - internal class CategoryDao + public class CategoryDao : ICategoryDao { + private CategoryDetails.Mapper summaryMapper = new(); + + public void CreateCategory(Category cat) + { + throw new NotImplementedException(); + } + + public void DeleteCategory(Category cat) + { + throw new NotImplementedException(); + } + + public List ListALlCategory() + { + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var categories = client.Get>("v1/categories"); + + return summaryMapper.ToModel(categories).ToList(); + } + catch (Exception ex) + { + Debug.WriteLine($"Exception non gérée lors de la récupération des catégories : {ex}"); + return new List(); + } + } + + public void UpdateCategory(Category category) + { + throw new NotImplementedException(); + } } } diff --git a/Couche IHM/GalliumPlusApi/Dao/LogDAO.cs b/Couche IHM/GalliumPlusApi/Dao/LogDAO.cs new file mode 100644 index 0000000..760fdf1 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/LogDAO.cs @@ -0,0 +1,18 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.Dao +{ + public class LogDAO : ILogDAO + { + public void CreateLog(Log log) + { + + } + + public List GetLogs(int mois, int annee) + { + return new(); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs index 48da904..08ff2eb 100644 --- a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs @@ -1,10 +1,14 @@ using Couche_Data.Interfaces; +using GalliumPlusApi.Dto; using Modeles; +using System.Diagnostics; namespace GalliumPlusApi.Dao { public class ProductDao : IProductDAO { + private ProductSummary.Mapper summaryMapper = new(); + public void CreateProduct(Product product) { throw new NotImplementedException(); @@ -12,7 +16,20 @@ public void CreateProduct(Product product) public List GetProducts() { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var products = client.Get>("v1/products"); + + return summaryMapper.ToModel(products).ToList(); + } + catch (Exception ex) + { + Debug.WriteLine($"Exception non gérée lors de la récupération des produits : {ex}"); + return new List(); + } } public void RemoveProduct(Product product) diff --git a/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs b/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs index 0cfd881..6edbcec 100644 --- a/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/SessionDao.cs @@ -8,19 +8,22 @@ namespace GalliumPlusApi.Dao public class SessionDao { private UserDetails.Mapper detailsMapper = new(); + private RoleDetails.Mapper roleMapper = new(); - public User? LogIn(string username, string password) + public (User, Role)? LogIn(string username, string password) { using var client = new GalliumPlusHttpClient(); - client.JsonOptions.PropertyNamingPolicy = null; // pas de casse chameau + client.JsonOptions.PropertyNamingPolicy = null; // pas de casse chameau en sortie try { var loggedIn = client.Post("v1/login", new { Username = username, Password = password }); + SessionStorage.Current.Put("token", loggedIn.Token); + if (loggedIn.User == null) return null; - return this.detailsMapper.ToModel(loggedIn.User); + return (detailsMapper.ToModel(loggedIn.User), roleMapper.ToModel(loggedIn.User.Role)); } catch (UnauthenticatedException) { diff --git a/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs b/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs new file mode 100644 index 0000000..eb556f6 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs @@ -0,0 +1,18 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.Dao +{ + public class StatAcompteDAO : IStatAcompteDAO + { + public void CreateStat(StatAcompte stat) + { + + } + + public List GetStat() + { + return new(); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs b/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs new file mode 100644 index 0000000..7bd452c --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs @@ -0,0 +1,18 @@ +using Couche_Data.Interfaces; +using Modeles; + +namespace GalliumPlusApi.Dao +{ + public class StatProduitDAO : IStatProduitDAO + { + public void CreateStat(StatProduit stat) + { + + } + + public List GetStat() + { + return new(); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs index f6732c9..e37a1e8 100644 --- a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs @@ -1,10 +1,15 @@ using Couche_Data.Interfaces; +using GalliumPlusApi.Dto; using Modeles; +using System.Diagnostics; namespace GalliumPlusApi.Dao { public class UserDao : IUserDAO { + private UserSummary.UserMapper usMapper = new(); + private RoleDetails.Mapper rdMapper = new(); + public void CreateCompte(User compte) { throw new NotImplementedException(); @@ -12,12 +17,42 @@ public void CreateCompte(User compte) public List GetComptes() { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var roles = client.Get>("v1/roles"); + int adherentRoleId = roles.Find(role => role.Name == "Adhérent")?.Id ?? -1; + + var users = client.Get>("v1/users") + .Where(user => user.Role != adherentRoleId); + + return usMapper.ToModel(users).ToList(); + } + catch (Exception ex) + { + Debug.WriteLine($"Exception non gérée lors de la récupération des utilisateurs : {ex}"); + return new List(); + } } public List GetRoles() { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var roles = client.Get>("v1/roles"); + + return rdMapper.ToModel(roles).ToList(); + } + catch (Exception ex) + { + Debug.WriteLine($"Exception non gérée lors de la récupération des rôles : {ex}"); + return new List(); + } } public void RemoveCompte(User compte) diff --git a/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs b/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs index 29dd88c..86c7066 100644 --- a/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs +++ b/Couche IHM/GalliumPlusApi/Dto/CategoryDetails.cs @@ -1,32 +1,23 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Stocks; -using System.ComponentModel.DataAnnotations; +using Modeles; -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class CategoryDetails { - public int Id { get; set; } - [Required] public string Name { get; set; } - - public CategoryDetails() - { - this.Id = -1; - this.Name = String.Empty; - } + public int Id { get; set; } = -1; + public string Name { get; set; } = String.Empty; public class Mapper : Mapper { public override CategoryDetails FromModel(Category model) { - return new CategoryDetails { Id = model.Id, Name = model.Name }; + return new CategoryDetails { Id = model.IdCat, Name = model.NomCategory }; } public override Category ToModel(CategoryDetails dto) { - return new Category(dto.Id, dto.Name); + return new Category(dto.Id, dto.Name, true); } } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs b/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs deleted file mode 100644 index a32e410..0000000 --- a/Couche IHM/GalliumPlusApi/Dto/ClientDetails.cs +++ /dev/null @@ -1,142 +0,0 @@ -/*using GalliumPlus.WebApi.Core.Applications; -using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Exceptions; -using GalliumPlus.WebApi.Core.Users; -using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; - -namespace GalliumPlus.WebApi.Dto -{ - public class ClientDetails - { - public enum ClientType { CLIENT, BOT_CLIENT, SSO_CLIENT } - - public ClientType? Type { get; set; } - public int Id { get; set; } - public string? ApiKey { get; set; } - [Required] public string Name { get; set; } - [Required] public uint? PermissionsGranted { get; set; } - [Required] public bool? IsEnabled { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public uint? PermissionsRevoked { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public bool? UsesApi { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? RedirectUrl { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? LogoUrl { get; set; } - - public ClientDetails() - { - this.Id = -1; - this.Name = String.Empty; - } - - public class Mapper : Mapper - { - public override ClientDetails FromModel(Client model) - { - ClientDetails dto = new() - { - Id = model.Id, - ApiKey = model.ApiKey, - Name = model.Name, - PermissionsGranted = (uint)model.Granted, - IsEnabled = model.IsEnabled, - }; - - if (model is BotClient) - { - dto.Type = ClientType.BOT_CLIENT; - } - else - { - dto.PermissionsRevoked = (uint)model.Revoked; - - if (model is SsoClient ssoClient) - { - dto.Type = ClientType.SSO_CLIENT; - dto.RedirectUrl = ssoClient.RedirectUrl; - dto.LogoUrl = ssoClient.LogoUrl; - dto.UsesApi = ssoClient.UsesApi; - } - else - { - dto.Type = ClientType.CLIENT; - } - } - - return dto; - } - - private static Exception MissingField() - { - return new InvalidItemException($"Les informations sur l'application sont incomplètes."); - } - - public override Client ToModel(ClientDetails dto) - { - if (!dto.Type.HasValue) - { - throw MissingField(); - } - - switch (dto.Type.Value) - { - case ClientType.CLIENT: - return new Client( - name: dto.Name, - isEnabled: dto.IsEnabled!.Value, - granted: (Permissions)dto.PermissionsGranted!.Value, - revoked: (Permissions)(dto.PermissionsRevoked ?? throw MissingField()) - ); - - case ClientType.BOT_CLIENT: - return new BotClient( - name: dto.Name, - isEnabled: dto.IsEnabled!.Value, - permissions: (Permissions)dto.PermissionsGranted!.Value - ); - - case ClientType.SSO_CLIENT: - return new SsoClient( - name: dto.Name, - isEnabled: dto.IsEnabled!.Value, - granted: (Permissions)dto.PermissionsGranted!.Value, - revoked: (Permissions)(dto.PermissionsRevoked ?? throw MissingField()), - usesApi: dto.UsesApi ?? throw MissingField(), - redirectUrl: dto.RedirectUrl ?? throw MissingField(), - logoUrl: dto.LogoUrl - ); - - default: - throw new InvalidItemException("Type de client invalide"); - } - } - - public void PatchModel(Client original, ClientDetails patch) - { - original.Name = patch.Name; - original.IsEnabled = patch.IsEnabled!.Value; - original.Granted = (Permissions)patch.PermissionsGranted!.Value; - - if (original is not BotClient) - { - original.Revoked = (Permissions)(patch.PermissionsRevoked ?? throw MissingField()); - - if (original is SsoClient originalSso) - { - originalSso.RedirectUrl = patch.RedirectUrl ?? throw MissingField(); - originalSso.UsesApi = patch.UsesApi ?? throw MissingField(); - originalSso.LogoUrl = patch.LogoUrl; - } - } - } - } - } -} -*/ \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/Mapper.cs b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs index 96823dc..b67ca31 100644 --- a/Couche IHM/GalliumPlusApi/Dto/Mapper.cs +++ b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs @@ -7,7 +7,7 @@ public virtual TModel ToModel(TDto dto) throw new InvalidOperationException("Ce DTO ne doit pas entrer !! >:("); } - public IEnumerable toModel(IEnumerable dtos) + public IEnumerable ToModel(IEnumerable dtos) { foreach (TDto dto in dtos) yield return ToModel(dto); } diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs index 3904c3b..5270495 100644 --- a/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs @@ -1,71 +1,45 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Exceptions; -using GalliumPlus.WebApi.Core.Stocks; -using System.ComponentModel.DataAnnotations; +using GalliumPlusApi.CompatibilityHelpers; +using Modeles; -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class ProductSummary { - public int Id { get; set; } - [Required] public string Name { get; set; } - [Required] public int? Stock { get; set; } - [Required] public decimal? NonMemberPrice { get; set; } - [Required] public decimal? MemberPrice { get; set; } - [Required] public Availability? Availability { get; set; } - [Required] public int? Category { get; set; } - - public ProductSummary() - { - this.Id = -1; - this.Name = string.Empty; - } + public int Id { get; set; } = -1; + public string Name { get; set; } = ""; + public int Stock { get; set; } = 0; + public decimal NonMemberPrice { get; set; } = -1; + public decimal MemberPrice { get; set; } = -1; + public string Availability { get; set; } = ""; + public int Category { get; set; } = -1; public class Mapper : Mapper { - private ICategoryDao categoryDao; - - public Mapper(ICategoryDao categoryDao) - { - this.categoryDao = categoryDao; - } - public override ProductSummary FromModel(Product model) { return new ProductSummary { - Id = model.Id, - Name = model.Name, - Stock = model.Stock, - NonMemberPrice = model.NonMemberPrice, - MemberPrice = model.MemberPrice, - Availability = model.Availability, - Category = model.Category.Id + Id = model.ID, + Name = model.NomProduit, + Stock = model.Quantite, + NonMemberPrice = Format.FloatToMonetary(model.PrixNonAdherent), + MemberPrice = Format.FloatToMonetary(model.PrixAdherent), + Availability = "AUTO", + Category = model.Categorie }; } public override Product ToModel(ProductSummary dto) { - Category category; - try - { - category = this.categoryDao.Read(dto.Category!.Value); - } - catch (ItemNotFoundException) - { - throw new InvalidItemException("La catégorie associée n'existe pas"); - } - return new Product( - dto.Id, dto.Name, - dto.Stock!.Value, - dto.NonMemberPrice!.Value, - dto.MemberPrice!.Value, - dto.Availability!.Value, - category + id: dto.Id, + nomProduit: dto.Name, + quantite: dto.Stock, + prixAdherent: (float)dto.MemberPrice, + prixNonAdherent: (float)dto.NonMemberPrice, + categorie: dto.Category ); } } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs index 655083c..8ae6e45 100644 --- a/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs +++ b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs @@ -1,4 +1,5 @@ -using Modeles; +using GalliumPlusApi.CompatibilityHelpers; +using Modeles; namespace GalliumPlusApi.Dto { diff --git a/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs index 05e8aad..eed0ddb 100644 --- a/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs @@ -1,79 +1,134 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Exceptions; -using GalliumPlus.WebApi.Core.Users; +using GalliumPlusApi.CompatibilityHelpers; +using GalliumPlusApi.ModelDecorators; +using Microsoft.VisualBasic; +using Modeles; using System.ComponentModel.DataAnnotations; -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class UserSummary { - [Required] public string Id { get; set; } - [Required] public string FirstName { get; set; } - [Required] public string LastName { get; set; } - [Required] public string Email { get; set; } - [Required] public int? Role { get; set; } - [Required] public string Year { get; set; } - public decimal? Deposit { get; set; } - [Required] public bool? IsMember { get; set; } + public string Id { get; set; } = string.Empty; + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public int Role { get; set; } = -1; + public string Year { get; set; } = string.Empty; + public decimal? Deposit { get; set; } = null; + public bool IsMember { get; set; } = false; - public UserSummary() + public class UserMapper : Mapper { - this.Id = String.Empty; - this.FirstName = String.Empty; - this.LastName = String.Empty; - this.Email = String.Empty; - this.Role = null; - this.Year = String.Empty; - this.Deposit = null; - this.IsMember = null; - } - - public class Mapper : Mapper - { - private IRoleDao roleDao; - - public Mapper(IRoleDao roleDao) + public override UserSummary FromModel(User user) { - this.roleDao = roleDao; - } + string year = "?"; + decimal? deposit = null; + bool isMember = true; + if (user is DecoratedUser deco) + { + year = deco.Year; + deposit = deco.Deposit; + isMember = deco.IsMember; + } + return new UserSummary + { + Id = UserIdRepository.Current.FindUsernameOf(user.ID), + FirstName = user.Prenom, + LastName = user.Nom, + Email = user.Mail, + Role = user.IdRole, + Year = year, + Deposit = deposit, + IsMember = isMember, + }; + } - public override UserSummary FromModel(User user) + public UserSummary PatchWithModel(UserDetails originialUser, User patch) { return new UserSummary { - Id = user.Id, - FirstName = user.Identity.FirstName, - LastName = user.Identity.LastName, - Email = user.Identity.Email, - Role = user.Role.Id, - Year = user.Identity.Year, - Deposit = user.Deposit, - IsMember = user.IsMember + Id = originialUser.Id, + FirstName = patch.Prenom, + LastName = patch.Nom, + Email = patch.Mail, + Role = patch.IdRole, + Year = originialUser.Year, + Deposit = originialUser.Deposit, + IsMember = originialUser.IsMember, }; } public override User ToModel(UserSummary summary) { - Role role; - try + return new DecoratedUser( + id: UserIdRepository.Current.GetIdFor(summary.Id), + nom: summary.LastName, + prenom: summary.FirstName, + mail: summary.Email, + password: "", + role: summary.Role, + year: summary.Year, + deposit: summary.Deposit, + isMember: summary.IsMember + ); + } + } + + public class AcompteMapper : Mapper + { + public override UserSummary FromModel(Acompte model) + { + string email = ""; + int roleId = -1; + if (model is DecoratedAcompte deco) { - role = this.roleDao.Read(summary.Role!.Value); + email = deco.Email; + roleId = deco.RoleId; } - catch (ItemNotFoundException) + + return new UserSummary { - throw new InvalidItemException("Le rôle associé n'existe pas"); - } + Deposit = Format.FloatToMonetary(model.Argent), + Email = email, + FirstName = model.Prenom, + Id = model.Identifiant, + IsMember = model.StillAdherent, + LastName = model.Nom, + Role = roleId, + Year = model.Formation, + }; + } - return new User( - summary.Id!, - new UserIdentity(summary.FirstName!, summary.LastName!, summary.Email!, summary.Year!), - role, - summary.Deposit!.Value, - summary.IsMember!.Value + public UserSummary PatchWithModel(UserDetails originalUser, Acompte patch) + { + return new UserSummary + { + Deposit = Format.FloatToMonetary(patch.Argent), + Email = originalUser.Email, + FirstName = patch.Prenom, + Id = patch.Identifiant, + IsMember = patch.StillAdherent, + LastName = patch.Nom, + Role = originalUser.Role.Id, + Year = patch.Formation, + }; + } + + public override Acompte ToModel(UserSummary dto) + { + return new DecoratedAcompte( + id: UserIdRepository.Current.GetIdFor(dto.Id), + identifiant: dto.Id, + nom: dto.LastName, + prenom: dto.FirstName, + argent: (float)dto.Deposit!, + formation: dto.Year, + stillAdherent: dto.IsMember, + email: dto.Email, + roleId: dto.Role ); } } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs index e25b4a2..e74c7cf 100644 --- a/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs +++ b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs @@ -11,7 +11,7 @@ public static void ThrowForStatus(HttpResponseMessage response) throw response.StatusCode switch { HttpStatusCode.Unauthorized => new UnauthenticatedException(), - _ => new GalliumPlusHttpException($"Erreur HTTP non gérée : {response.StatusCode} {response.ReasonPhrase}"), + _ => new GalliumPlusHttpException($"Erreur HTTP non gérée : {(int)response.StatusCode} {response.ReasonPhrase}"), }; } } diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs index 860c4e6..9b4d0f9 100644 --- a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs +++ b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs @@ -1,6 +1,8 @@ using GalliumPlusApi.Exceptions; +using MySqlX.XDevAPI; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Net.Http.Json; using System.Text; @@ -20,6 +22,12 @@ public GalliumPlusHttpClient() BaseAddress = new Uri("https://" + ApiConfig.Current.Host); DefaultRequestHeaders.Add("X-Api-Key", ApiConfig.Current.ApiKey); jsonOptions = new JsonSerializerOptions(); + jsonOptions.PropertyNameCaseInsensitive = true; + } + + public void UseSessionToken(string token) + { + DefaultRequestHeaders.Add("Authorization", $"Bearer {token}"); } private static T WaitForTask(Task task) @@ -34,6 +42,16 @@ private static T WaitForTask(Task task) return task.Result; } + public T Get(string resource) + { + var response = WaitForTask(this.GetAsync(resource)); + + ExceptionFactory.ThrowForStatus(response); + + return WaitForTask(response.Content.ReadFromJsonAsync(jsonOptions)) + ?? throw new NullReferenceException("Json deserialisation return null"); + } + public T Post(string resource, object data) { var response = WaitForTask(this.PostAsJsonAsync(resource, data, jsonOptions)); @@ -44,7 +62,5 @@ public T Post(string resource, object data) ?? throw new NullReferenceException("Json deserialisation return null"); } - // public T Get(string url) - } } diff --git a/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedAcompte.cs b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedAcompte.cs new file mode 100644 index 0000000..c3b142f --- /dev/null +++ b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedAcompte.cs @@ -0,0 +1,31 @@ +using Modeles; + +namespace GalliumPlusApi.ModelDecorators +{ + public class DecoratedAcompte : Acompte + { + private string email; + private int roleId; + + public string Email => email; + + public int RoleId => roleId; + + public DecoratedAcompte( + int id, + string identifiant, + string nom, + string prenom, + float argent, + string formation, + bool stillAdherent, + string email, + int roleId + ) + : base(id, identifiant, nom, prenom, argent, formation, stillAdherent) + { + this.email = email; + this.roleId = roleId; + } + } +} diff --git a/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedUser.cs b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedUser.cs new file mode 100644 index 0000000..e1827e8 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedUser.cs @@ -0,0 +1,35 @@ +using Modeles; + +namespace GalliumPlusApi.ModelDecorators +{ + internal class DecoratedUser : User + { + private string year; + private decimal? deposit; + private bool isMember; + + public string Year => year; + + public decimal? Deposit => deposit; + + public bool IsMember => isMember; + + public DecoratedUser( + int id, + string nom, + string prenom, + string mail, + string password, + int role, + string year, + decimal? deposit, + bool isMember + ) + : base(id, nom, prenom, mail, password, role) + { + this.year = year; + this.deposit = deposit; + this.isMember = isMember; + } + } +} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs deleted file mode 100644 index 152faeb..0000000 --- a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderAcompteDao.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; - -namespace GalliumPlusApi.PlaceholderDao -{ - public class PlaceholderAcompteDao : IAcompteDao - { - public void CreateAdhérent(Acompte adhérent) - { - - } - - public List GetAdhérents() - { - return new List(); - } - - public void RemoveAdhérent(Acompte adhérent) - { - - } - - public void UpdateAdhérent(Acompte adhérent) - { - - } - } -} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs deleted file mode 100644 index 6e76adb..0000000 --- a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderCategoryDao.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; - -namespace GalliumPlusApi.PlaceholderDao -{ - public class PlaceholderCategoryDao : ICategoryDao - { - public void CreateCategory(Category cat) - { - - } - - public void DeleteCategory(Category cat) - { - - } - - public List ListALlCategory() - { - return new List(); - } - - public void UpdateCategory(Category category) - { - - } - } -} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs deleted file mode 100644 index 0d9b6d8..0000000 --- a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderProductDao.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; - -namespace GalliumPlusApi.PlaceholderDao -{ - public class PlaceholderProductDao : IProductDAO - { - public void CreateProduct(Product product) - { - - } - - public List GetProducts() - { - return new List(); - } - - public void RemoveProduct(Product product) - { - - } - - public void UpdateProduct(Product product) - { - - } - } -} diff --git a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs b/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs deleted file mode 100644 index 1956e3a..0000000 --- a/Couche IHM/GalliumPlusApi/PlaceholderDao/PlaceholderUserDao.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GalliumPlusApi.PlaceholderDao -{ - public class PlaceholderUserDao : IUserDAO - { - public void CreateCompte(User compte) - { - - } - - public List GetComptes() - { - return new List(); - } - - public List GetRoles() - { - return new List(); - } - - public void RemoveCompte(User compte) - { - - } - - public void UpdateCompte(User compte) - { - - } - } -} diff --git a/Couche IHM/GalliumPlusApi/SessionStorage.cs b/Couche IHM/GalliumPlusApi/SessionStorage.cs new file mode 100644 index 0000000..fc09ce0 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/SessionStorage.cs @@ -0,0 +1,48 @@ +using System.Collections.Concurrent; + +namespace GalliumPlusApi +{ + public class SessionStorage + { + private static SessionStorage? current; + + public static SessionStorage Current + { + get + { + if (current == null) + { + current = new SessionStorage(); + } + return current; + } + } + + ConcurrentDictionary storage; + + private SessionStorage() + { + storage = new(); + } + + public void Put(string key, object value) + { + storage[key] = value; + } + + public object Get(string key) + { + return storage[key]; + } + + public T Get(string key) + { + return (T)storage[key]; + } + + public void Remove(string key) + { + storage.TryRemove(key, out var _); + } + } +} From b041b571f649c6ff7365a6569ae71929fba6581f Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Mon, 30 Oct 2023 18:10:29 +0100 Subject: [PATCH 04/56] =?UTF-8?q?Gestion=20des=20cat=C3=A9gories?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Couche IHM/Couche IHM/ConnexionIHM.xaml.cs | 7 +----- Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs | 19 +++++++++++---- .../GalliumPlusApi/GalliumPlusHttpClient.cs | 23 ++++++++++++++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs index e82b7e3..73c0da3 100644 --- a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs +++ b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs @@ -73,13 +73,8 @@ private void ConnectToAccount(object sender, RoutedEventArgs e) catch(Exception ex) { messageQueue?.Enqueue("Vous n'êtes pas connecté à Internet"); - } - - + } } - - - } } } diff --git a/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs index 5c2318f..61bb620 100644 --- a/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/CategoryDao.cs @@ -7,16 +7,22 @@ namespace GalliumPlusApi.Dao { public class CategoryDao : ICategoryDao { - private CategoryDetails.Mapper summaryMapper = new(); + private CategoryDetails.Mapper mapper = new(); public void CreateCategory(Category cat) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Post($"v1/categories", mapper.FromModel(cat)); } public void DeleteCategory(Category cat) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Delete($"v1/categories/{cat.IdCat}"); } public List ListALlCategory() @@ -28,7 +34,7 @@ public List ListALlCategory() { var categories = client.Get>("v1/categories"); - return summaryMapper.ToModel(categories).ToList(); + return mapper.ToModel(categories).ToList(); } catch (Exception ex) { @@ -39,7 +45,10 @@ public List ListALlCategory() public void UpdateCategory(Category category) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Put($"v1/categories/{category.IdCat}", mapper.FromModel(category)); } } } diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs index 9b4d0f9..6cb7e2e 100644 --- a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs +++ b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs @@ -1,4 +1,5 @@ -using GalliumPlusApi.Exceptions; +using GalliumPlusApi.Dto; +using GalliumPlusApi.Exceptions; using MySqlX.XDevAPI; using System; using System.Collections.Generic; @@ -62,5 +63,25 @@ public T Post(string resource, object data) ?? throw new NullReferenceException("Json deserialisation return null"); } + public void Post(string resource, object data) + { + var response = WaitForTask(this.PostAsJsonAsync(resource, data, jsonOptions)); + + ExceptionFactory.ThrowForStatus(response); + } + + public void Put(string resource, object data) + { + var response = WaitForTask(this.PutAsJsonAsync(resource, data, jsonOptions)); + + ExceptionFactory.ThrowForStatus(response); + } + + public void Delete(string resource) + { + var response = WaitForTask(this.DeleteAsync(resource)); + + ExceptionFactory.ThrowForStatus(response); + } } } From 418831f8d114adb5a91f54e90bc8fbe7c1d86907 Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Mon, 30 Oct 2023 18:54:29 +0100 Subject: [PATCH 05/56] Gestion des produits --- Couche IHM/GalliumPlusApi/Dao/ProductDao.cs | 28 +++++-- .../GalliumPlusApi/Dto/ProductDetails.cs | 77 +++---------------- .../GalliumPlusApi/Dto/ProductSummary.cs | 23 +++++- .../GalliumPlusApi/GalliumPlusHttpClient.cs | 6 ++ .../ModelDecorators/DecoratedProduct.cs | 25 ++++++ Couche IHM/GalliumPlusApi/SessionStorage.cs | 6 +- 6 files changed, 90 insertions(+), 75 deletions(-) create mode 100644 Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedProduct.cs diff --git a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs index 08ff2eb..db7180d 100644 --- a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs @@ -1,5 +1,6 @@ using Couche_Data.Interfaces; using GalliumPlusApi.Dto; +using GalliumPlusApi.ModelDecorators; using Modeles; using System.Diagnostics; @@ -7,11 +8,14 @@ namespace GalliumPlusApi.Dao { public class ProductDao : IProductDAO { - private ProductSummary.Mapper summaryMapper = new(); + private ProductSummary.Mapper mapper = new(); public void CreateProduct(Product product) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Post("v1/products", mapper.FromModel(product)); } public List GetProducts() @@ -23,7 +27,7 @@ public List GetProducts() { var products = client.Get>("v1/products"); - return summaryMapper.ToModel(products).ToList(); + return mapper.ToModel(products).ToList(); } catch (Exception ex) { @@ -34,12 +38,26 @@ public List GetProducts() public void RemoveProduct(Product product) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Delete($"v1/products/{product.ID}"); } public void UpdateProduct(Product product) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + if (product is DecoratedProduct deco) + { + client.Put($"v1/products/{product.ID}", mapper.FromModel(product)); + } + else + { + var original = client.Get($"v1/products/{product.ID}"); + client.Put($"v1/products/{product.ID}", mapper.PatchWithModel(original, product)); + } } } } diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs index e1a8e30..ef1bd3f 100644 --- a/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs +++ b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs @@ -1,70 +1,13 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Stocks; - -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class ProductDetails { - public int Id { get; set; } - public string Name { get; set; } - public int Stock { get; set; } - public decimal NonMemberPrice { get; set; } - public decimal MemberPrice { get; set; } - public Availability Availability { get; set; } - public bool Available { get; set; } - public CategoryDetails Category { get; set; } - - public ProductDetails( - int id, - string name, - int stock, - decimal nonMemberPrice, - decimal memberPrice, - Availability availability, - bool available, - CategoryDetails category) - { - this.Id = id; - this.Name = name; - this.Stock = stock; - this.NonMemberPrice = nonMemberPrice; - this.MemberPrice = memberPrice; - this.Availability = availability; - this.Available = available; - this.Category = category; - } - - public class Mapper : Mapper - { - private CategoryDetails.Mapper categoryMapper = new(); - - public override ProductDetails FromModel(Product model) - { - return new ProductDetails( - model.Id, - model.Name, - model.Stock, - model.NonMemberPrice, - model.MemberPrice, - model.Availability, - model.Available, - this.categoryMapper.FromModel(model.Category) - ); - } - - public override Product ToModel(ProductDetails dto) - { - return new Product( - dto.Id, - dto.Name, - dto.Stock, - dto.NonMemberPrice, - dto.MemberPrice, - dto.Availability, - this.categoryMapper.ToModel(dto.Category) - ); - } - } - } -} -*/ \ No newline at end of file + public int Id { get; set; } = -1; + public string Name { get; set; } = ""; + public int Stock { get; set; } = 0; + public decimal NonMemberPrice { get; set; } = -1; + public decimal MemberPrice { get; set; } = -1; + public string Availability { get; set; } = ""; + public bool Available { get; set; } = true; + public CategoryDetails Category { get; set; } = new(); +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs index 5270495..4085e47 100644 --- a/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/ProductSummary.cs @@ -1,4 +1,5 @@ using GalliumPlusApi.CompatibilityHelpers; +using GalliumPlusApi.ModelDecorators; using Modeles; namespace GalliumPlusApi.Dto @@ -17,6 +18,12 @@ public class Mapper : Mapper { public override ProductSummary FromModel(Product model) { + string availability = "AUTO"; + if (model is DecoratedProduct deco) + { + availability = deco.Availability; + } + return new ProductSummary { Id = model.ID, @@ -24,11 +31,25 @@ public override ProductSummary FromModel(Product model) Stock = model.Quantite, NonMemberPrice = Format.FloatToMonetary(model.PrixNonAdherent), MemberPrice = Format.FloatToMonetary(model.PrixAdherent), - Availability = "AUTO", + Availability = availability, Category = model.Categorie }; } + public ProductSummary PatchWithModel(ProductDetails originalProduct, Product patch) + { + return new ProductSummary + { + Id = patch.ID, + Name = patch.NomProduit, + Stock = patch.Quantite, + NonMemberPrice = Format.FloatToMonetary(patch.PrixNonAdherent), + MemberPrice = Format.FloatToMonetary(patch.PrixAdherent), + Availability = originalProduct.Availability, + Category = patch.Categorie + }; + } + public override Product ToModel(ProductSummary dto) { return new Product( diff --git a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs index 6cb7e2e..42be45c 100644 --- a/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs +++ b/Couche IHM/GalliumPlusApi/GalliumPlusHttpClient.cs @@ -43,6 +43,12 @@ private static T WaitForTask(Task task) return task.Result; } + public async Task LookUpVersionAsync() + { + var response = await this.GetAsync(""); + return response.Headers.GetValues("x-gallium-version").First(); + } + public T Get(string resource) { var response = WaitForTask(this.GetAsync(resource)); diff --git a/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedProduct.cs b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedProduct.cs new file mode 100644 index 0000000..fca1b24 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/ModelDecorators/DecoratedProduct.cs @@ -0,0 +1,25 @@ +using Modeles; + +namespace GalliumPlusApi.ModelDecorators +{ + internal class DecoratedProduct : Product + { + private string availability; + + public string Availability => availability; + + public DecoratedProduct( + int id, + string nomProduit, + int quantite, + float prixAdherent, + float prixNonAdherent, + int categorie, + string availability + ) + : base (id, nomProduit, quantite, prixAdherent, prixNonAdherent, categorie) + { + this.availability = availability; + } + } +} diff --git a/Couche IHM/GalliumPlusApi/SessionStorage.cs b/Couche IHM/GalliumPlusApi/SessionStorage.cs index fc09ce0..f1131b2 100644 --- a/Couche IHM/GalliumPlusApi/SessionStorage.cs +++ b/Couche IHM/GalliumPlusApi/SessionStorage.cs @@ -25,9 +25,10 @@ private SessionStorage() storage = new(); } - public void Put(string key, object value) + public SessionStorage Put(string key, object value) { storage[key] = value; + return this; } public object Get(string key) @@ -40,9 +41,10 @@ public T Get(string key) return (T)storage[key]; } - public void Remove(string key) + public SessionStorage Remove(string key) { storage.TryRemove(key, out var _); + return this; } } } From 185d2ab439cf93e25036b9de62a819d6b4d96f3c Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Tue, 31 Oct 2023 15:07:33 +0100 Subject: [PATCH 06/56] =?UTF-8?q?Gestion=20des=20utilisateurs/adh=C3=A9ren?= =?UTF-8?q?ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Couche IHM/BindingRules/RuleIDFormat.cs | 26 +++++--- Couche IHM/Couche IHM/ConnexionIHM.xaml.cs | 7 +- .../Couche IHM/Frames/FrameAcompte.xaml | 2 +- Couche IHM/Couche IHM/Frames/FrameCaisse.xaml | 26 ++++---- Couche IHM/Couche IHM/MainWindow.xaml.cs | 10 ++- .../Couche IHM/MessageBoxErrorHandler.cs | 35 ++++++++++ .../Couche IHM/VueModeles/AcompteViewModel.cs | 64 +++++++++---------- .../VueModeles/CategoryViewModel.cs | 20 +++--- .../VueModeles/MainWindowViewModel.cs | 30 +++++---- .../Couche IHM/VueModeles/ProductViewModel.cs | 59 +++++++++-------- .../VueModeles/ProductsViewModel.cs | 56 ++++++++-------- .../Couche IHM/VueModeles/UserViewModel.cs | 6 +- .../CompatibilityHelpers/Random.cs | 18 ++++++ Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs | 40 +++++++++++- Couche IHM/GalliumPlusApi/Dao/ProductDao.cs | 2 +- Couche IHM/GalliumPlusApi/Dao/UserDao.cs | 41 ++++++++++-- Couche IHM/GalliumPlusApi/Dto/Error.cs | 36 +++++++++++ .../GalliumPlusApi/Dto/ProductDetails.cs | 1 + Couche IHM/GalliumPlusApi/Dto/UserDetails.cs | 38 +++++------ Couche IHM/GalliumPlusApi/Dto/UserSummary.cs | 4 +- .../Exceptions/ExceptionFactory.cs | 30 ++++++++- .../Exceptions/InvalidItemException.cs | 9 +++ .../Exceptions/ItemNotFoundException.cs | 9 +++ .../Exceptions/PermissionDeniedException.cs | 9 +++ .../Exceptions/UnauthenticatedException.cs | 2 +- 25 files changed, 405 insertions(+), 175 deletions(-) create mode 100644 Couche IHM/Couche IHM/MessageBoxErrorHandler.cs create mode 100644 Couche IHM/GalliumPlusApi/CompatibilityHelpers/Random.cs create mode 100644 Couche IHM/GalliumPlusApi/Dto/Error.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/InvalidItemException.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/ItemNotFoundException.cs create mode 100644 Couche IHM/GalliumPlusApi/Exceptions/PermissionDeniedException.cs diff --git a/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs b/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs index b8fe7e6..e4c5c5f 100644 --- a/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs +++ b/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.ConstrainedExecution; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -26,23 +27,28 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo) AcompteViewModel adh = MainWindowViewModel.Instance.AdherentViewModel.CurrentAcompte; string identifiant = (string)value; - if (identifiant.Length > 2) + if (identifiant.Length == 0) { - string nom = adh.NomIHM; - string prenom = adh.PrenomIHM; - if (identifiant[0] != prenom.ToLower()[0] || identifiant[1] != nom.ToLower()[0]) - { - result = new ValidationResult(false, "Format invalide"); - } + result = new ValidationResult(false, "Veuillez saisir un nom d'utilisateur"); + } + else if (identifiant.Length > 20) + { + result = new ValidationResult(false, "Un nom d'utilisateur ne peut pas dépasser 20 caractères"); } else { - result = new ValidationResult(false, "Format invalide"); + if (identifiant.Any(c => !IsAsciiAndLowerCaseLetterOrDigit(c))) + { + result = new ValidationResult(false, "Un nom d'utilisateur doit comprendre uniquement des lettre minuscules et des chiffres"); + } } - - return result; } + + private static bool IsAsciiAndLowerCaseLetterOrDigit(char c) + { + return char.IsAscii(c) && (char.IsLower(c) || char.IsDigit(c)); + } } } diff --git a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs index 73c0da3..2ad8265 100644 --- a/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs +++ b/Couche IHM/Couche IHM/ConnexionIHM.xaml.cs @@ -56,14 +56,15 @@ private void ConnectToAccount(object sender, RoutedEventArgs e) User? user = UserManager.ConnectCompte(identifiant, password); if (user != null) { + MainWindow mainWindow = new MainWindow(user); + mainWindow.Show(); + this.Close(); + userManager = MainWindowViewModel.Instance.UserManager; logManager = MainWindowViewModel.Instance.LogManager; Log log = new Log(DateTime.Now, 1, $"Connexion de {user.Prenom} {user.Nom}", $"{user.Prenom} {user.Nom}"); logManager.CreateLog(log); MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); - MainWindow mainWindow = new MainWindow(user, logManager, userManager); - mainWindow.Show(); - this.Close(); } else { diff --git a/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml b/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml index 3d84a73..0f37493 100644 --- a/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml +++ b/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml @@ -463,7 +463,7 @@ Margin="20,20,20,10" materialDesign:HintAssist.Hint="Identifiant de l'acompte" Style="{StaticResource MaterialDesignFilledTextBox}" - MaxLength="8"> + MaxLength="20"> - - - - - - - - - + + + + + + + - + - - + + - - + + diff --git a/Couche IHM/Couche IHM/MainWindow.xaml.cs b/Couche IHM/Couche IHM/MainWindow.xaml.cs index a128148..0b6c92f 100644 --- a/Couche IHM/Couche IHM/MainWindow.xaml.cs +++ b/Couche IHM/Couche IHM/MainWindow.xaml.cs @@ -18,10 +18,11 @@ public partial class MainWindow : Window /// /// Constructeur de la mainwindow /// - public MainWindow(User user,LogManager logManager,UserManager userManager) + public MainWindow(User user) { InitializeComponent(); - MainWindowViewModel.Instance.CompteConnected = new UserViewModel(user,userManager); + var mwvm = MainWindowViewModel.GetInstanceFor(this); + mwvm.CompteConnected = new UserViewModel(user, mwvm.UserManager); DataContext = MainWindowViewModel.Instance; } @@ -31,6 +32,11 @@ public MainWindow(User user,LogManager logManager,UserManager userManager) /// /// private void Disconnect(object sender, RoutedEventArgs e) + { + this.AskToDisconnect(); + } + + public void AskToDisconnect() { ConnexionIHM connexionIHM = new ConnexionIHM(); connexionIHM.Show(); diff --git a/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs b/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs new file mode 100644 index 0000000..1fd5410 --- /dev/null +++ b/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs @@ -0,0 +1,35 @@ +using Couche_IHM.VueModeles; +using GalliumPlusApi.Exceptions; +using System; +using System.Windows; + +namespace Couche_IHM +{ + public static class MessageBoxErrorHandler + { + public static Action AttachToAction(Action action) + { + return input => Handle(() => action(input)); + } + + public static bool Handle(Action action) + { + try + { + action(); + return true; + } + catch (UnauthenticatedException) + { + MessageBox.Show("Veuillez vous reconnecter.", "Session expirée", MessageBoxButton.OK, MessageBoxImage.Error); + MainWindowViewModel.Instance.MainWindow.AskToDisconnect(); + return false; + } + catch (Exception error) + { + MessageBox.Show(error.Message, "Erreur", MessageBoxButton.OK, MessageBoxImage.Error); + return false; + } + } + } +} diff --git a/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs b/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs index 3fc73ad..1687c6f 100644 --- a/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs @@ -172,19 +172,19 @@ public AcompteViewModel(Acompte acompte,AcompteManager acompteManager,string act private void DeleteAcompte() { // Modifier la data - this.acompteManager.RemoveAdhérent(this.acompte); - - // Log l'action - Log log = new Log(DateTime.Now, 2, $"Suppresion de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + if (MessageBoxErrorHandler.Handle(() => this.acompteManager.RemoveAdhérent(this.acompte))) + { + // Log l'action + Log log = new Log(DateTime.Now, 2, $"Suppresion de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); - // Notifier la vue - MainWindowViewModel.Instance.AdherentViewModel.RemoveAcompte(this); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); - MainWindowViewModel.Instance.AdherentViewModel.DialogModifAdherent = false; - MainWindowViewModel.Instance.AdherentViewModel.ShowModifButtons = false; + // Notifier la vue + MainWindowViewModel.Instance.AdherentViewModel.RemoveAcompte(this); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + MainWindowViewModel.Instance.AdherentViewModel.DialogModifAdherent = false; + MainWindowViewModel.Instance.AdherentViewModel.ShowModifButtons = false; + } ShowConfirmationDelete = false; - } /// @@ -192,7 +192,6 @@ private void DeleteAcompte() /// private void CreateAcompte() { - // Changer la data this.acompte.Nom = this.nomIHM; this.acompte.Prenom = this.prenomIHM; @@ -201,30 +200,30 @@ private void CreateAcompte() this.acompte.Identifiant = this.identifiantIHM; this.acompte.StillAdherent = this.isAdherentIHM; this.action = "UPDATE"; - acompteManager.CreateAdhérent(this.acompte); - - // Log l'action - Log log = new Log(DateTime.Now, 2, $"Création de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + + if (MessageBoxErrorHandler.Handle(() => acompteManager.CreateAdhérent(this.acompte))) + { + // Log l'action + Log log = new Log(DateTime.Now, 2, $"Création de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); - // Notifier la vue - MainWindowViewModel.Instance.AdherentViewModel.AddAcompte(this); - NotifyPropertyChanged(nameof(this.Action)); - NotifyPropertyChanged(nameof(IdentifiantIHM)); - NotifyPropertyChanged(nameof(ArgentIHM)); - NotifyPropertyChanged(nameof(NomCompletIHM)); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + // Notifier la vue + MainWindowViewModel.Instance.AdherentViewModel.AddAcompte(this); + NotifyPropertyChanged(nameof(this.Action)); + NotifyPropertyChanged(nameof(IdentifiantIHM)); + NotifyPropertyChanged(nameof(ArgentIHM)); + NotifyPropertyChanged(nameof(NomCompletIHM)); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + } MainWindowViewModel.Instance.AdherentViewModel.DialogModifAdherent = false; MainWindowViewModel.Instance.AdherentViewModel.ShowModifButtons = false; } - /// /// Permet de mettre à jour visuellement les modifications de l'adhérent /// public void UpdateAcompte(bool doLog = true) { - // Log l'action float argent = ConverterFormatArgent.ConvertToDouble(this.ArgentIHM); if (doLog && acompte.Argent != argent) @@ -244,7 +243,6 @@ public void UpdateAcompte(bool doLog = true) MainWindowViewModel.Instance.LogManager.CreateLog(log); MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); } - // Changer la data this.acompte.Nom = this.nomIHM; @@ -253,12 +251,14 @@ public void UpdateAcompte(bool doLog = true) this.acompte.Formation = this.formationIHM; this.acompte.Identifiant = this.identifiantIHM; this.acompte.StillAdherent = this.isAdherentIHM; - acompteManager.UpdateAdhérent(this.acompte); - // Notifier la vue - NotifyPropertyChanged(nameof(IdentifiantIHM)); - NotifyPropertyChanged(nameof(ArgentIHM)); - NotifyPropertyChanged(nameof(NomCompletIHM)); + if (MessageBoxErrorHandler.Handle(() => acompteManager.UpdateAdhérent(this.acompte))) + { + // Notifier la vue + NotifyPropertyChanged(nameof(IdentifiantIHM)); + NotifyPropertyChanged(nameof(ArgentIHM)); + NotifyPropertyChanged(nameof(NomCompletIHM)); + } MainWindowViewModel.Instance.AdherentViewModel.DialogModifAdherent = false; MainWindowViewModel.Instance.AdherentViewModel.ShowModifButtons = false; } diff --git a/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs b/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs index 97577c6..dfe8361 100644 --- a/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs @@ -97,8 +97,8 @@ public CategoryViewModel(CategoryManager categoryManager,Category category) public void ActivateCategory() { // Mise à jour data - category.Visible = !this.invisible; - this.categoryManager.UpdateCategory(category); + category.Visible = true; + // TOUJOURS VISIBLE AHAHAHHAHA this.categoryManager.UpdateCategory(category); } /// @@ -108,7 +108,7 @@ public void UpdateCategory() { // Mise à jour data category.NomCategory = this.nomCat; - this.categoryManager.UpdateCategory(category); + MessageBoxErrorHandler.Handle(()=> this.categoryManager.UpdateCategory(category)); } @@ -130,14 +130,16 @@ public void ResetCategory() public void DeleteCategory() { // Mise à jour data - this.categoryManager.DeleteCategory(category); - foreach (ProductViewModel prod in MainWindowViewModel.Instance.ProductViewModel.Products.ToList().FindAll(x => x.CategoryIHM == this)) + if (MessageBoxErrorHandler.Handle(() => this.categoryManager.DeleteCategory(category))) { - prod.DeleteCatNotify(); + foreach (ProductViewModel prod in MainWindowViewModel.Instance.ProductViewModel.Products.ToList().FindAll(x => x.CategoryIHM == this)) + { + prod.DeleteCatNotify(); + } + + // Notifier la vue + MainWindowViewModel.Instance.ProductViewModel.Categories.Remove(this); } - - // Notifier la vue - MainWindowViewModel.Instance.ProductViewModel.Categories.Remove(this); } diff --git a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs index 8266a60..5177ff9 100644 --- a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs @@ -18,16 +18,16 @@ public class MainWindowViewModel : INotifyPropertyChanged { #region singleton private static MainWindowViewModel instance = null; - public static MainWindowViewModel Instance + + public static MainWindowViewModel Instance => instance ?? throw new NullReferenceException("Le MainWindowViewModel doit d'abord être instancié par la fenêtre."); + + public static MainWindowViewModel GetInstanceFor(MainWindow mainWindow) { - get + if (instance == null) { - if (instance == null) - { - instance = new MainWindowViewModel(); - } - return instance; + instance = new MainWindowViewModel(mainWindow); } + return instance; } #endregion @@ -48,6 +48,7 @@ public static MainWindowViewModel Instance private LogsViewModel logsViewModel; private UsersViewModel userViewModel; private StatistiqueViewModel statViewModel; + private MainWindow mainWindow; #endregion #region notify @@ -133,30 +134,31 @@ public Uri Uri } } - + public MainWindow MainWindow => mainWindow; #endregion /// /// Constructeur du mainwindow vue modele /// - private MainWindowViewModel() + private MainWindowViewModel(MainWindow mainWindow) { - this.logManager = new LogManager(); - this.userManager = new UserManager(); + this.logManager = new LogManager(); + this.userManager = new UserManager(); this.productManager = new ProductManager(); this.acompteManager = new AcompteManager(); this.statAcompteManager = new StatAcompteManager(); this.statProduitManager = new StatProduitManager(); this.adherentViewModel = new AcomptesViewModel(acompteManager); this.productViewModel = new ProductsViewModel(productManager); - this.caisseViewModel = new CaisseViewModel(this.statAcompteManager,this.statProduitManager); - this.statViewModel = new StatistiqueViewModel(productManager, acompteManager,statAcompteManager,statProduitManager); + this.caisseViewModel = new CaisseViewModel(this.statAcompteManager, this.statProduitManager); + this.statViewModel = new StatistiqueViewModel(productManager, acompteManager, statAcompteManager, statProduitManager); this.logsViewModel = new LogsViewModel(userManager, logManager); this.userViewModel = new UsersViewModel(this.userManager); this.partenariatViewModel = new PartenariatViewModel(); - + this.mainWindow = mainWindow; + // Initialisation des events this.ChangeFrame = new RelayCommand(fram => this.Frame = (Frame)fram); } diff --git a/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs b/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs index 64c0ee7..4c8ad1a 100644 --- a/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs @@ -289,14 +289,16 @@ public void UpdateProduct(bool doLog = true) this.product.Categorie = this.categoryManager.ListAllCategory().Find(x => x.NomCategory == categoryIHM.NomCat).IdCat; this.product.PrixAdherent = ConverterFormatArgent.ConvertToDouble(this.prixAdherentIHM); this.product.PrixNonAdherent = ConverterFormatArgent.ConvertToDouble(this.prixNonAdherentIHM); - this.productManager.UpdateProduct(this.product); + if (MessageBoxErrorHandler.Handle(() => this.productManager.UpdateProduct(this.product))) + { - // Notifier la vue - NotifyPropertyChanged(nameof(NomProduitIHM)); - NotifyPropertyChanged(nameof(PrixAdherentIHM)); - NotifyPropertyChanged(nameof(QuantiteIHM)); - NotifyPropertyChanged(nameof(CategoryIHM)); - NotifyPropertyChanged(nameof(isDisponible)); + // Notifier la vue + NotifyPropertyChanged(nameof(NomProduitIHM)); + NotifyPropertyChanged(nameof(PrixAdherentIHM)); + NotifyPropertyChanged(nameof(QuantiteIHM)); + NotifyPropertyChanged(nameof(CategoryIHM)); + NotifyPropertyChanged(nameof(isDisponible)); + } MainWindowViewModel.Instance.ProductViewModel.ShowProductDetail = false; MainWindowViewModel.Instance.ProductViewModel.ShowModifButtons = false; } @@ -313,15 +315,17 @@ public void UpdateProduct(bool doLog = true) public void DeleteProduct() { // Changer la data - this.productManager.RemoveProduct(this.product); + if (MessageBoxErrorHandler.Handle(() => this.productManager.RemoveProduct(this.product))) + { - // Log l'action - Log log = new Log(DateTime.Now, 3, $"Suppression du produit : {this.NomProduitIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + // Log l'action + Log log = new Log(DateTime.Now, 3, $"Suppression du produit : {this.NomProduitIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); - // Notifier la vue - MainWindowViewModel.Instance.ProductViewModel.RemoveProduct(this); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + // Notifier la vue + MainWindowViewModel.Instance.ProductViewModel.RemoveProduct(this); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + } MainWindowViewModel.Instance.ProductViewModel.ShowProductDetail = false; MainWindowViewModel.Instance.ProductViewModel.ShowModifButtons = false; this.ShowConfirmationDelete = false; @@ -344,21 +348,24 @@ public void CreateProduct() this.product.Categorie = this.categoryManager.ListAllCategory().Find(x => x.NomCategory == categoryIHM.NomCat).IdCat; this.product.PrixAdherent = ConverterFormatArgent.ConvertToDouble(this.prixAdherentIHM); this.product.PrixNonAdherent = ConverterFormatArgent.ConvertToDouble(this.prixNonAdherentIHM); - this.productManager.CreateProduct(this.product); - this.action = "UPDATE"; - // Log l'action - Log log = new Log(DateTime.Now, 3, $"Ajout du produit : {product.NomProduit}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + if (MessageBoxErrorHandler.Handle(() => this.productManager.CreateProduct(this.product))) + { + this.action = "UPDATE"; + // Log l'action + Log log = new Log(DateTime.Now, 3, $"Ajout du produit : {product.NomProduit}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); - // Notifier la vue - MainWindowViewModel.Instance.ProductViewModel.AddProduct(this); - NotifyPropertyChanged(nameof(NomProduitIHM)); - NotifyPropertyChanged(nameof(QuantiteIHM)); - NotifyPropertyChanged(nameof(CategoryIHM)); - NotifyPropertyChanged(nameof(isDisponible)); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + + // Notifier la vue + MainWindowViewModel.Instance.ProductViewModel.AddProduct(this); + NotifyPropertyChanged(nameof(NomProduitIHM)); + NotifyPropertyChanged(nameof(QuantiteIHM)); + NotifyPropertyChanged(nameof(CategoryIHM)); + NotifyPropertyChanged(nameof(isDisponible)); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + } MainWindowViewModel.Instance.ProductViewModel.ShowProductDetail = false; MainWindowViewModel.Instance.ProductViewModel.ShowModifButtons = false; } diff --git a/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs b/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs index 0d9baf2..259cb40 100644 --- a/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs @@ -108,9 +108,9 @@ public ObservableCollection Products return produitsIHM; } - set - { - products = value; + set + { + products = value; } } @@ -133,23 +133,23 @@ public bool ShowModifButtons public string SearchFilter { get => searchFilter; - set + set { searchFilter = value; NotifyPropertyChanged(nameof(Products)); - - } + + } } /// /// Permet de montrer la popup du produit /// - public bool ShowProductDetail - { + public bool ShowProductDetail + { get => showProductDetail; - set - { - showProductDetail = value; + set + { + showProductDetail = value; NotifyPropertyChanged(nameof(ShowProductDetail)); } } @@ -157,12 +157,12 @@ public bool ShowProductDetail /// /// Permet d'afficher la popup des catégories /// - public bool ShowCategories - { + public bool ShowCategories + { get => showCategories; set - { - showCategories = value; + { + showCategories = value; NotifyPropertyChanged(); } } @@ -170,10 +170,10 @@ public bool ShowCategories /// /// Permet d'afficher l'icone pour supprimer un produit /// - public bool ShowDeleteProduct - { + public bool ShowDeleteProduct + { get => showDeleteProduct; - set + set { if (MainWindowViewModel.Instance.CompteConnected.RoleIHM.Name != "Conseil d'administration") { @@ -243,8 +243,8 @@ private void InitProducts() { catProduit = categories.Find(x => x.Id == prd.Categorie); } - - this.products.Add(new ProductViewModel(prd,this.productManager,this.categoryManager,catProduit)); + + this.products.Add(new ProductViewModel(prd, this.productManager, this.categoryManager, catProduit)); } } @@ -257,7 +257,7 @@ private void InitCategories() List categories = this.categoryManager.ListAllCategory(); foreach (Category cat in categories) { - this.categories.Add(new CategoryViewModel(this.categoryManager,cat)); + this.categories.Add(new CategoryViewModel(this.categoryManager, cat)); } } @@ -271,13 +271,13 @@ private void OpenProductDetails(string action) if (action == "NEW" || currentProduct == null || currentProduct.Action == "NEW") { ShowDeleteProduct = false; - CurrentProduct = new ProductViewModel(new Product(),this.productManager,this.categoryManager ,null,"NEW"); + CurrentProduct = new ProductViewModel(new Product(), this.productManager, this.categoryManager, null, "NEW"); } else { ShowDeleteProduct = true; } - + ShowProductDetail = true; } @@ -287,11 +287,13 @@ private void OpenProductDetails(string action) public void CreateCategory() { // Mise à jour data - CategoryViewModel cat = new CategoryViewModel(this.categoryManager,new Category(0,"New",true)); - this.categoryManager.CreateCategory(cat.Category); + CategoryViewModel cat = new CategoryViewModel(this.categoryManager, new Category(0, "New", true)); + if (MessageBoxErrorHandler.Handle(() => this.categoryManager.CreateCategory(cat.Category))) + { - // Notifier la vue - Categories.Add(cat); + // Notifier la vue + Categories.Add(cat); + } } diff --git a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs index 7e44baa..7c77ce6 100644 --- a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs @@ -149,9 +149,9 @@ public UserViewModel(User user, UserManager userManager) { MainWindowViewModel.Instance.UserViewModel.CurrentUser = this; MainWindowViewModel.Instance.UserViewModel.OpenUserDetails("UPDATE"); }); - this.UpdateU = new RelayCommand(x => this.UpdateUser()); - this.CreateU = new RelayCommand(x => this.CreateUser()); - this.DeleteU = new RelayCommand(x => this.DeleteUser()); + this.UpdateU = new RelayCommand(MessageBoxErrorHandler.AttachToAction(x => this.UpdateUser())); + this.CreateU = new RelayCommand(MessageBoxErrorHandler.AttachToAction(x => this.CreateUser())); + this.DeleteU = new RelayCommand(MessageBoxErrorHandler.AttachToAction(x => this.DeleteUser())); this.CancelDeleteU= new RelayCommand(x => ShowConfirmationDelete = false); this.PreviewDeleteU = new RelayCommand(x => this.ShowConfirmationDelete = true); } diff --git a/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Random.cs b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Random.cs new file mode 100644 index 0000000..d23c04f --- /dev/null +++ b/Couche IHM/GalliumPlusApi/CompatibilityHelpers/Random.cs @@ -0,0 +1,18 @@ +using System.Text; + +namespace GalliumPlusApi.CompatibilityHelpers +{ + internal static class RandomHelper + { + public static string RandomUsername() + { + Random rng = new(); + StringBuilder sb = new("user"); + for (int i = 0; i < 6; i++) + { + sb.Append(rng.Next(0, 10)); + } + return sb.ToString(); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs index 38b01f3..da83bad 100644 --- a/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/AcompteDao.cs @@ -1,16 +1,33 @@ using Couche_Data.Interfaces; +using GalliumPlusApi.CompatibilityHelpers; using GalliumPlusApi.Dto; +using GalliumPlusApi.Exceptions; +using GalliumPlusApi.ModelDecorators; using Modeles; using System.Diagnostics; +using static GalliumPlusApi.Dto.UserSummary; +using System.Numerics; namespace GalliumPlusApi.Dao { public class AcompteDao : IAcompteDao { private UserSummary.AcompteMapper mapper = new(); + public void CreateAdhérent(Acompte adhérent) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + try + { + var existingUser = client.Get($"v1/users/{adhérent.Identifiant}"); + client.Put($"v1/users/{adhérent.Identifiant}", mapper.PatchWithModel(existingUser, adhérent)); + } + catch (ItemNotFoundException) + { + client.Post("v1/users", mapper.FromModel(adhérent)); + } } public List GetAdhérents() @@ -34,12 +51,29 @@ public List GetAdhérents() public void RemoveAdhérent(Acompte adhérent) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + var existingUser = client.Get($"v1/users/{adhérent.Identifiant}"); + existingUser.Deposit = null; + + client.Put($"v1/users/{adhérent.Identifiant}", existingUser.AsUserSummary); } public void UpdateAdhérent(Acompte adhérent) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + if (adhérent is DecoratedAcompte deco) + { + client.Put($"v1/users/{adhérent.Identifiant}", mapper.FromModel(deco)); + } + else + { + var original = client.Get($"v1/users/{adhérent.Identifiant}"); + client.Put($"v1/products/{adhérent.Identifiant}", mapper.PatchWithModel(original, adhérent)); + } } } } diff --git a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs index db7180d..47e3bad 100644 --- a/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/ProductDao.cs @@ -51,7 +51,7 @@ public void UpdateProduct(Product product) if (product is DecoratedProduct deco) { - client.Put($"v1/products/{product.ID}", mapper.FromModel(product)); + client.Put($"v1/products/{product.ID}", mapper.FromModel(deco)); } else { diff --git a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs index e37a1e8..d573bd2 100644 --- a/Couche IHM/GalliumPlusApi/Dao/UserDao.cs +++ b/Couche IHM/GalliumPlusApi/Dao/UserDao.cs @@ -1,5 +1,7 @@ using Couche_Data.Interfaces; +using GalliumPlusApi.CompatibilityHelpers; using GalliumPlusApi.Dto; +using GalliumPlusApi.ModelDecorators; using Modeles; using System.Diagnostics; @@ -7,12 +9,17 @@ namespace GalliumPlusApi.Dao { public class UserDao : IUserDAO { - private UserSummary.UserMapper usMapper = new(); - private RoleDetails.Mapper rdMapper = new(); + private UserSummary.UserMapper userMapper = new(); + private RoleDetails.Mapper roleMapper = new(); public void CreateCompte(User compte) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + compte.ID = UserIdRepository.Current.GetIdFor(RandomHelper.RandomUsername()); + + client.Post("v1/users", userMapper.FromModel(compte)); } public List GetComptes() @@ -25,10 +32,12 @@ public List GetComptes() var roles = client.Get>("v1/roles"); int adherentRoleId = roles.Find(role => role.Name == "Adhérent")?.Id ?? -1; + SessionStorage.Current.Put("adherentRoleId", adherentRoleId); + var users = client.Get>("v1/users") .Where(user => user.Role != adherentRoleId); - return usMapper.ToModel(users).ToList(); + return userMapper.ToModel(users).ToList(); } catch (Exception ex) { @@ -46,7 +55,7 @@ public List GetRoles() { var roles = client.Get>("v1/roles"); - return rdMapper.ToModel(roles).ToList(); + return roleMapper.ToModel(roles).ToList(); } catch (Exception ex) { @@ -57,12 +66,30 @@ public List GetRoles() public void RemoveCompte(User compte) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + string username = UserIdRepository.Current.FindUsernameOf(compte.ID); + + client.Delete($"v1/users/{username}"); } public void UpdateCompte(User compte) { - throw new NotImplementedException(); + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + string username = UserIdRepository.Current.FindUsernameOf(compte.ID); + + if (compte is DecoratedUser deco) + { + client.Put($"v1/users/{username}", userMapper.FromModel(deco)); + } + else + { + var original = client.Get($"v1/users/{username}"); + client.Put($"v1/products/{username}", userMapper.PatchWithModel(original, compte)); + } } } } diff --git a/Couche IHM/GalliumPlusApi/Dto/Error.cs b/Couche IHM/GalliumPlusApi/Dto/Error.cs new file mode 100644 index 0000000..107dd6c --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dto/Error.cs @@ -0,0 +1,36 @@ +using System.Diagnostics; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace GalliumPlusApi.Dto +{ + public class Error + { + public string Code { get; set; } = "UNKNOWN"; + + public string Message { get; set; } = "Erreur inconnue."; + + public object? DebugInfo { get; set; } = null; + + public string DetailedMessage + { + get + { + StringBuilder sb = new(); + sb.Append(Message); + + if (DebugInfo != null) + { + sb.Append("\n\nInformations de débogage:\n"); + sb.Append(JsonSerializer.Serialize(DebugInfo, new JsonSerializerOptions { WriteIndented = true })); + } + else + { + sb.Append("\n\nAucune informations de débogage."); + } + return sb.ToString(); + } + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs index ef1bd3f..a416980 100644 --- a/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs +++ b/Couche IHM/GalliumPlusApi/Dto/ProductDetails.cs @@ -10,4 +10,5 @@ public class ProductDetails public string Availability { get; set; } = ""; public bool Available { get; set; } = true; public CategoryDetails Category { get; set; } = new(); + } } \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs index 8ae6e45..fd5c5cb 100644 --- a/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs +++ b/Couche IHM/GalliumPlusApi/Dto/UserDetails.cs @@ -1,30 +1,32 @@ using GalliumPlusApi.CompatibilityHelpers; using Modeles; +using System.Text.Json.Serialization; namespace GalliumPlusApi.Dto { public class UserDetails { - public string Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public string Email { get; set; } - public RoleDetails Role { get; set; } - public string Year { get; set; } - public decimal? Deposit { get; set; } - public bool IsMember { get; set; } + public string Id { get; set; } = ""; + public string FirstName { get; set; } = ""; + public string LastName { get; set; } = ""; + public string Email { get; set; } = ""; + public RoleDetails Role { get; set; } = new(); + public string Year { get; set; } = ""; + public decimal? Deposit { get; set; } = null; + public bool IsMember { get; set; } = false; - public UserDetails() + [JsonIgnore] + public UserSummary AsUserSummary => new() { - Id = ""; - FirstName = ""; - LastName = ""; - Email = ""; - Role = new(); - Year = ""; - Deposit = null; - IsMember = false; - } + Deposit = Deposit, + Email = Email, + FirstName = FirstName, + LastName = LastName, + Id = Id, + IsMember = IsMember, + Role = Role.Id, + Year = Year, + }; public class Mapper : Mapper { diff --git a/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs index eed0ddb..51e4a29 100644 --- a/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/UserSummary.cs @@ -79,8 +79,8 @@ public class AcompteMapper : Mapper { public override UserSummary FromModel(Acompte model) { - string email = ""; - int roleId = -1; + string email = "UKN"; + int roleId = SessionStorage.Current.Get("adherentRoleId"); if (model is DecoratedAcompte deco) { email = deco.Email; diff --git a/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs index e74c7cf..7c69aaa 100644 --- a/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs +++ b/Couche IHM/GalliumPlusApi/Exceptions/ExceptionFactory.cs @@ -1,19 +1,45 @@ -using System.Net; +using GalliumPlusApi.Dto; +using System.Net; +using System.Net.Http.Json; +using System.Text.Json; namespace GalliumPlusApi.Exceptions { internal static class ExceptionFactory { - public static void ThrowForStatus(HttpResponseMessage response) + public static void ThrowForStatus(HttpResponseMessage response, JsonSerializerOptions? jsonOptions = null) { if (!response.IsSuccessStatusCode) { throw response.StatusCode switch { HttpStatusCode.Unauthorized => new UnauthenticatedException(), + HttpStatusCode.BadRequest => ResponseToException(response, jsonOptions) ?? new InvalidItemException(), + HttpStatusCode.Forbidden => ResponseToException(response, jsonOptions) ?? new PermissionDeniedException(), + HttpStatusCode.NotFound => ResponseToException(response, jsonOptions) ?? new ItemNotFoundException(), _ => new GalliumPlusHttpException($"Erreur HTTP non gérée : {(int)response.StatusCode} {response.ReasonPhrase}"), }; } } + + private static GalliumPlusHttpException? ResponseToException(HttpResponseMessage response, JsonSerializerOptions? jsonOptions) + { + Task task = response.Content.ReadFromJsonAsync(jsonOptions); + task.Wait(); + if (task.Result is Error error) + { + return error.Code switch + { + "InvalidItem" => new InvalidItemException(error.DetailedMessage), + "PermissionDenied" => new PermissionDeniedException(error.DetailedMessage), + "ItemNotFound" => new ItemNotFoundException(error.DetailedMessage), + _ => throw new NotImplementedException($"Code d'erreur non géré : « {error.Code} »") + }; + } + else + { + return null; + } + } } } diff --git a/Couche IHM/GalliumPlusApi/Exceptions/InvalidItemException.cs b/Couche IHM/GalliumPlusApi/Exceptions/InvalidItemException.cs new file mode 100644 index 0000000..2ec7eb6 --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/InvalidItemException.cs @@ -0,0 +1,9 @@ +namespace GalliumPlusApi.Exceptions +{ + public class InvalidItemException : GalliumPlusHttpException + { + public InvalidItemException() : base("Ressource invalide") { } + + public InvalidItemException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Exceptions/ItemNotFoundException.cs b/Couche IHM/GalliumPlusApi/Exceptions/ItemNotFoundException.cs new file mode 100644 index 0000000..11e4c9a --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/ItemNotFoundException.cs @@ -0,0 +1,9 @@ +namespace GalliumPlusApi.Exceptions +{ + internal class ItemNotFoundException : GalliumPlusHttpException + { + public ItemNotFoundException() : base("Le ressource demandée n'existe pas") { } + + public ItemNotFoundException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Exceptions/PermissionDeniedException.cs b/Couche IHM/GalliumPlusApi/Exceptions/PermissionDeniedException.cs new file mode 100644 index 0000000..6b6b92e --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Exceptions/PermissionDeniedException.cs @@ -0,0 +1,9 @@ +namespace GalliumPlusApi.Exceptions +{ + public class PermissionDeniedException : GalliumPlusHttpException + { + public PermissionDeniedException() : base("Permission refusée.") { } + + public PermissionDeniedException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs b/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs index f3f6ad7..47c6425 100644 --- a/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs +++ b/Couche IHM/GalliumPlusApi/Exceptions/UnauthenticatedException.cs @@ -2,6 +2,6 @@ { public class UnauthenticatedException : GalliumPlusHttpException { - public UnauthenticatedException() : base() { } + public UnauthenticatedException() : base("Requête non authentifiée.") { } } } From a8a1e008fca08086027160e56a0409634be8b51e Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Tue, 31 Oct 2023 15:48:15 +0100 Subject: [PATCH 07/56] =?UTF-8?q?Connexion=20avec=20la=20base=20de=20donn?= =?UTF-8?q?=C3=A9es=20GalliumV2=20pour=20les=20statistiques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ Couche IHM/Couche Data/Dao/StatAcompteDAO.cs | 3 +-- Couche IHM/Couche Data/Dao/StatProduitDAO.cs | 4 +--- Couche IHM/Couche Data/Dao/dbsDAO.cs | 22 +++++++++++++++++-- .../Manager/StatAcompteManager.cs" | 13 ++++++++--- .../Manager/StatProduitManager.cs" | 11 +++++++++- 6 files changed, 44 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 02b32dc..b3df6e9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +ConnectionString.txt + # User-specific files *.rsuser *.suo diff --git a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs index 909e50c..253fccf 100644 --- a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs @@ -11,8 +11,7 @@ public class StatAcompteDAO : IStatAcompteDAO public List GetStat() { //Connection - string connString ="nope"; - MySqlConnection sql = new MySqlConnection(connString); + MySqlConnection sql = new MySqlConnection(dbsDAO.ConnectionString); sql.Open(); //Requette SQL diff --git a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs index 0e3bbca..c4cab45 100644 --- a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs @@ -10,9 +10,7 @@ public class StatProduitDAO : IStatProduitDAO public List GetStat() { - //Connection - string connString = "nope"; - MySqlConnection sql = new MySqlConnection(connString); + MySqlConnection sql = new MySqlConnection(dbsDAO.ConnectionString); sql.Open(); //Requette SQL diff --git a/Couche IHM/Couche Data/Dao/dbsDAO.cs b/Couche IHM/Couche Data/Dao/dbsDAO.cs index 9d0884c..e37641d 100644 --- a/Couche IHM/Couche Data/Dao/dbsDAO.cs +++ b/Couche IHM/Couche Data/Dao/dbsDAO.cs @@ -1,4 +1,5 @@ using MySql.Data.MySqlClient; +using System.Reflection; namespace Couche_Data.Dao { @@ -75,13 +76,30 @@ public object DatabaseLock get { return databaseLock; } } + private static string? connectionString; + + public static string ConnectionString + { + get + { + if (connectionString == null) + { + var assembly = Assembly.GetExecutingAssembly(); + string resourceName = assembly.GetManifestResourceNames().Single(str => str.EndsWith("ConnectionString.txt")); + using Stream stream = assembly.GetManifestResourceStream(resourceName)!; + using StreamReader reader = new StreamReader(stream); + connectionString = reader.ReadToEnd(); + } + return connectionString; + } + } + /// /// Se connecte à la base de donnée /// private void ConnexionToBdd() { - string connString = "nope"; - this.sql = new MySqlConnection(connString); + sql = new MySqlConnection(ConnectionString); } /// diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" index 2ad9a9a..29d5120 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" @@ -1,5 +1,4 @@ -using Couche_Data; -using Couche_Data.Dao; +using Couche_Data.Dao; using Couche_Data.Interfaces; using GalliumPlusApi.Dao; using Modeles; @@ -26,7 +25,15 @@ public class StatAcompteManager /// public StatAcompteManager() { - dao = new GalliumPlusApi.Dao.StatAcompteDAO(); + try + { + dao = new Couche_Data.Dao.StatAcompteDAO(); + } + catch (Exception error) + { + Console.WriteLine("Impossible de se connecter à la base de donnée GV2 : " + error.Message); + dao = new GalliumPlusApi.Dao.StatAcompteDAO(); + } this.statAcompteList = new List(); Task.Run(() => this.statAcompteList = dao.GetStat()); diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" index dff7c67..113095b 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" @@ -24,7 +24,16 @@ public class StatProduitManager /// public StatProduitManager() { - dao = new StatProduitDAO(); + + try + { + dao = new Couche_Data.Dao.StatProduitDAO(); + } + catch (Exception error) + { + Console.WriteLine("Impossible de se connecter à la base de donnée GV2 : " + error.Message); + dao = new GalliumPlusApi.Dao.StatProduitDAO(); + } statProduitList = new(); Task.Run(()=> statProduitList = dao.GetStat()); } From efcca3843b843c65cc8bb1a6425e75a1dd5b19bf Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Tue, 31 Oct 2023 17:44:24 +0100 Subject: [PATCH 08/56] Paiements avec l'API --- Couche IHM/Couche Data/Couche Data.csproj | 8 + Couche IHM/Couche Data/Dao/StatAcompteDAO.cs | 71 +++++---- Couche IHM/Couche Data/Dao/StatProduitDAO.cs | 70 +++++---- .../Couche Data/Interfaces/IOrderDao.cs | 14 ++ .../Couche IHM/MessageBoxErrorHandler.cs | 4 +- .../Couche IHM/VueModeles/AcompteViewModel.cs | 8 +- .../Couche IHM/VueModeles/CaisseViewModel.cs | 146 +++++++++++------- .../VueModeles/CategoryViewModel.cs | 4 +- .../VueModeles/MainWindowViewModel.cs | 4 +- .../Couche IHM/VueModeles/ProductViewModel.cs | 6 +- .../VueModeles/ProductsViewModel.cs | 2 +- .../Couche IHM/VueModeles/UserViewModel.cs | 46 +++--- .../Manager/OrderManager.cs" | 41 +++++ .../Manager/StatAcompteManager.cs" | 10 +- .../Manager/StatProduitManager.cs" | 11 +- Couche IHM/GalliumPlusApi/Dao/OrderDao.cs | 19 +++ .../GalliumPlusApi/Dao/StatAcompteDAO.cs | 18 --- .../GalliumPlusApi/Dao/StatProduitDAO.cs | 18 --- Couche IHM/GalliumPlusApi/Dto/Error.cs | 3 +- Couche IHM/GalliumPlusApi/Dto/Mapper.cs | 5 + .../GalliumPlusApi/Dto/OrderItemSummary.cs | 32 +--- Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs | 79 ++-------- Couche IHM/Modeles/Category.cs | 3 +- Couche IHM/Modeles/Order.cs | 35 +++++ 24 files changed, 355 insertions(+), 302 deletions(-) create mode 100644 Couche IHM/Couche Data/Interfaces/IOrderDao.cs create mode 100644 "Couche IHM/Couche M\303\251tier/Manager/OrderManager.cs" create mode 100644 Couche IHM/GalliumPlusApi/Dao/OrderDao.cs delete mode 100644 Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs delete mode 100644 Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs create mode 100644 Couche IHM/Modeles/Order.cs diff --git a/Couche IHM/Couche Data/Couche Data.csproj b/Couche IHM/Couche Data/Couche Data.csproj index 3e3f7b3..3ae2ba6 100644 --- a/Couche IHM/Couche Data/Couche Data.csproj +++ b/Couche IHM/Couche Data/Couche Data.csproj @@ -7,6 +7,14 @@ enable + + + + + + + + diff --git a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs index 253fccf..957b47d 100644 --- a/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatAcompteDAO.cs @@ -1,7 +1,7 @@ using Couche_Data.Interfaces; using Modeles; using MySql.Data.MySqlClient; - +using System.Diagnostics; namespace Couche_Data.Dao { @@ -12,46 +12,59 @@ public List GetStat() { //Connection MySqlConnection sql = new MySqlConnection(dbsDAO.ConnectionString); - sql.Open(); + try + { + sql.Open(); + + //Requette SQL + string stm = "SELECT acompte_id,sum(amount) as argent FROM best_acomptes WHERE YEARWEEK(date) = YEARWEEK(CURRENT_DATE) group by acompte_id order by argent desc"; + MySqlCommand cmd = new MySqlCommand(stm, sql); + cmd.Prepare(); - //Requette SQL - string stm = "SELECT acompte_id,sum(amount) as argent FROM best_acomptes WHERE YEARWEEK(date) = YEARWEEK(CURRENT_DATE) group by acompte_id order by argent desc"; - MySqlCommand cmd = new MySqlCommand(stm, sql); - cmd.Prepare(); + //lecture de la requette + MySqlDataReader rdr = cmd.ExecuteReader(); - //lecture de la requette - MySqlDataReader rdr = cmd.ExecuteReader(); + List statAcompteList = new List(); + while (rdr.Read()) + { + statAcompteList.Add(new StatAcompte(0, DateTime.Now, rdr.GetFloat("argent"), rdr.GetInt16("acompte_id"))); + } - List statAcompteList = new List(); - while (rdr.Read()) + rdr.Close(); + sql.Close(); + return statAcompteList; + } + catch (Exception ex) { - statAcompteList.Add(new StatAcompte(0, DateTime.Now, rdr.GetFloat("argent"), rdr.GetInt16("acompte_id"))); + Debug.WriteLine($"Erreur pendant le chargement des stats acompte : {ex.Message}"); + return new(); } - - rdr.Close(); - sql.Close(); - return statAcompteList; } - - public void CreateStat(StatAcompte stat) { - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); - MySqlConnection sql = new MySqlConnection(connString); - sql.Open(); + try + { + string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); + MySqlConnection sql = new MySqlConnection(connString); + sql.Open(); - //Requette SQL - string formattedDate = stat.Date.ToString("yyyy-MM-dd"); - string formattedAmountMoney = stat.Money.ToString(System.Globalization.CultureInfo.InvariantCulture); - string stm = $"INSERT INTO best_acomptes VALUES(0,{formattedAmountMoney},'{formattedDate}',{stat.Acompte_Id})"; - MySqlCommand cmd = new MySqlCommand(stm, sql); - cmd.Prepare(); + //Requette SQL + string formattedDate = stat.Date.ToString("yyyy-MM-dd"); + string formattedAmountMoney = stat.Money.ToString(System.Globalization.CultureInfo.InvariantCulture); + string stm = $"INSERT INTO best_acomptes VALUES(0,{formattedAmountMoney},'{formattedDate}',{stat.Acompte_Id})"; + MySqlCommand cmd = new MySqlCommand(stm, sql); + cmd.Prepare(); - //lecture de la requette - cmd.ExecuteNonQuery(); + //lecture de la requette + cmd.ExecuteNonQuery(); - sql.Close(); + sql.Close(); + } + catch (Exception ex) + { + Debug.WriteLine($"Erreur pendant l'ajout d'une stat acompte : {ex.Message}"); + } } } } diff --git a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs index c4cab45..dd2972f 100644 --- a/Couche IHM/Couche Data/Dao/StatProduitDAO.cs +++ b/Couche IHM/Couche Data/Dao/StatProduitDAO.cs @@ -1,7 +1,7 @@ using Couche_Data.Interfaces; using Modeles; using MySql.Data.MySqlClient; - +using System.Diagnostics; namespace Couche_Data.Dao { @@ -11,46 +11,58 @@ public class StatProduitDAO : IStatProduitDAO public List GetStat() { MySqlConnection sql = new MySqlConnection(dbsDAO.ConnectionString); - sql.Open(); + try + { + sql.Open(); + + //Requette SQL + string stm = "SELECT product_id,sum(number_sales) as nb FROM best_sales WHERE YEARWEEK(date_sale) = YEARWEEK(CURRENT_DATE) group by product_id order by nb desc"; + MySqlCommand cmd = new MySqlCommand(stm, sql); + cmd.Prepare(); - //Requette SQL - string stm = "SELECT product_id,sum(number_sales) as nb FROM best_sales WHERE YEARWEEK(date_sale) = YEARWEEK(CURRENT_DATE) group by product_id order by nb desc"; - MySqlCommand cmd = new MySqlCommand(stm, sql); - cmd.Prepare(); + //lecture de la requette + MySqlDataReader rdr = cmd.ExecuteReader(); - //lecture de la requette - MySqlDataReader rdr = cmd.ExecuteReader(); + List statProduitList = new List(); + while (rdr.Read()) + { + statProduitList.Add(new StatProduit(0, DateTime.Now, rdr.GetInt16("nb"), rdr.GetInt16("product_id"))); + } - List statProduitList = new List(); - while (rdr.Read()) + rdr.Close(); + sql.Close(); + return statProduitList; + } + catch (Exception ex) { - statProduitList.Add(new StatProduit(0, DateTime.Now, rdr.GetInt16("nb"), rdr.GetInt16("product_id"))); + Debug.WriteLine($"Erreur pendant le chargement des stats produit : {ex.Message}"); + return new(); } - - rdr.Close(); - sql.Close(); - return statProduitList; } - - public void CreateStat(StatProduit stat) { - string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); - MySqlConnection sql = new MySqlConnection(connString); - sql.Open(); - - //Requette SQL - string formattedDate = stat.Date.ToString("yyyy-MM-dd"); - string stm = $"INSERT INTO best_sales VALUES(0,'{formattedDate}',{stat.Number_sales},{stat.Product_id})"; - MySqlCommand cmd = new MySqlCommand(stm, sql); - cmd.Prepare(); + try + { + string connString = String.Format("server={0};port={1};user id={2};password={3};database={4};SslMode={5}", "51.178.36.43", "3306", "c2_gallium", "DfD2no5UJc_nB", "c2_etismash", "none"); + MySqlConnection sql = new MySqlConnection(connString); + sql.Open(); - //lecture de la requette - cmd.ExecuteNonQuery(); + //Requette SQL + string formattedDate = stat.Date.ToString("yyyy-MM-dd"); + string stm = $"INSERT INTO best_sales VALUES(0,'{formattedDate}',{stat.Number_sales},{stat.Product_id})"; + MySqlCommand cmd = new MySqlCommand(stm, sql); + cmd.Prepare(); - sql.Close(); + //lecture de la requette + cmd.ExecuteNonQuery(); + sql.Close(); + } + catch (Exception ex) + { + Debug.WriteLine($"Erreur pendant l'ajout d'une stat produit : {ex.Message}"); + } } } } diff --git a/Couche IHM/Couche Data/Interfaces/IOrderDao.cs b/Couche IHM/Couche Data/Interfaces/IOrderDao.cs new file mode 100644 index 0000000..d24dd5d --- /dev/null +++ b/Couche IHM/Couche Data/Interfaces/IOrderDao.cs @@ -0,0 +1,14 @@ +using Modeles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Couche_Data.Interfaces +{ + public interface IOrderDao + { + void ProcessOrder(Order order); + } +} diff --git a/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs b/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs index 1fd5410..a69b29c 100644 --- a/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs +++ b/Couche IHM/Couche IHM/MessageBoxErrorHandler.cs @@ -9,10 +9,10 @@ public static class MessageBoxErrorHandler { public static Action AttachToAction(Action action) { - return input => Handle(() => action(input)); + return input => DoesntThrow(() => action(input)); } - public static bool Handle(Action action) + public static bool DoesntThrow(Action action) { try { diff --git a/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs b/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs index 1687c6f..dfc6ea4 100644 --- a/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/AcompteViewModel.cs @@ -172,7 +172,7 @@ public AcompteViewModel(Acompte acompte,AcompteManager acompteManager,string act private void DeleteAcompte() { // Modifier la data - if (MessageBoxErrorHandler.Handle(() => this.acompteManager.RemoveAdhérent(this.acompte))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.acompteManager.RemoveAdhérent(this.acompte))) { // Log l'action Log log = new Log(DateTime.Now, 2, $"Suppresion de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); @@ -201,7 +201,7 @@ private void CreateAcompte() this.acompte.StillAdherent = this.isAdherentIHM; this.action = "UPDATE"; - if (MessageBoxErrorHandler.Handle(() => acompteManager.CreateAdhérent(this.acompte))) + if (MessageBoxErrorHandler.DoesntThrow(() => acompteManager.CreateAdhérent(this.acompte))) { // Log l'action Log log = new Log(DateTime.Now, 2, $"Création de l acompte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); @@ -222,7 +222,7 @@ private void CreateAcompte() /// /// Permet de mettre à jour visuellement les modifications de l'adhérent /// - public void UpdateAcompte(bool doLog = true) + public void UpdateAcompte(bool doLog = true, bool persistChanges = true) { // Log l'action float argent = ConverterFormatArgent.ConvertToDouble(this.ArgentIHM); @@ -252,7 +252,7 @@ public void UpdateAcompte(bool doLog = true) this.acompte.Identifiant = this.identifiantIHM; this.acompte.StillAdherent = this.isAdherentIHM; - if (MessageBoxErrorHandler.Handle(() => acompteManager.UpdateAdhérent(this.acompte))) + if (persistChanges && MessageBoxErrorHandler.DoesntThrow(() => acompteManager.UpdateAdhérent(this.acompte))) { // Notifier la vue NotifyPropertyChanged(nameof(IdentifiantIHM)); diff --git a/Couche IHM/Couche IHM/VueModeles/CaisseViewModel.cs b/Couche IHM/Couche IHM/VueModeles/CaisseViewModel.cs index 407253a..bc147fb 100644 --- a/Couche IHM/Couche IHM/VueModeles/CaisseViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/CaisseViewModel.cs @@ -15,7 +15,7 @@ namespace Couche_IHM.VueModeles public class CaisseViewModel : INotifyPropertyChanged { #region attributes - private ObservableDictionary productOrder = new ObservableDictionary(); + private ObservableDictionary productOrder = new ObservableDictionary(); private string currentPaiement; private bool showPayAcompte = false; private bool showPayPaypal = false; @@ -26,23 +26,25 @@ public class CaisseViewModel : INotifyPropertyChanged private AcompteViewModel adherentPayer = null; private StatProduitManager statProduitManager; private StatAcompteManager statAcompteManager; + private OrderManager orderManager; #endregion #region constructor /// /// Constructeur de caisse vue modele /// - public CaisseViewModel(StatAcompteManager statAcompte,StatProduitManager statProduit) + public CaisseViewModel(StatAcompteManager statAcompte, StatProduitManager statProduit, OrderManager orderManager) { // Initialisation objets métier this.statProduitManager = statProduit; this.statAcompteManager = statAcompte; + this.orderManager = orderManager; // Initialisation events this.AddProd = new RelayCommand(prodIHM => AddProduct(prodIHM)); this.RemoveProd = new RelayCommand(prodIHM => RemoveProduct(prodIHM)); this.ShowPay = new RelayCommand(x => PreviewPayArticles()); - this.CancelPay = new RelayCommand(x => + this.CancelPay = new RelayCommand(x => { this.ShowPayPaypal = false; this.ShowPayBanque = false; @@ -57,7 +59,7 @@ public CaisseViewModel(StatAcompteManager statAcompte,StatProduitManager statPro this.NotifyPropertyChanged(nameof(this.PriceAdherIHM)); this.NotifyPropertyChanged(nameof(this.PriceNonAdherIHM)); - }); + }); this.CurrentPaiement = Paiements[0]; } #endregion @@ -76,7 +78,7 @@ private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") public RelayCommand AddProd { get; set; } public RelayCommand RemoveProd { get; set; } public RelayCommand CancelPay { get; set; } - public RelayCommand Pay { get; set; } + public RelayCommand Pay { get; set; } public RelayCommand ShowPay { get; set; } #endregion @@ -104,7 +106,7 @@ public float PriceAdher float prixTotal = 0.00f; foreach (ProductViewModel product in productOrder.Keys) { - prixTotal += (float)ConverterFormatArgent.ConvertToDouble(product.PrixAdherentIHM) * productOrder[product]; + prixTotal += (float)ConverterFormatArgent.ConvertToDouble(product.PrixAdherentIHM) * productOrder[product]; } return prixTotal; } @@ -150,19 +152,19 @@ public float PriceNanAdher /// Représente les produits du panier /// public ObservableDictionary ProductOrder - { - get => productOrder; - set => productOrder = value; + { + get => productOrder; + set => productOrder = value; } /// /// Représente le moyen de paiement sélectionné /// - public string CurrentPaiement - { + public string CurrentPaiement + { get => currentPaiement; - set - { + set + { currentPaiement = value; NotifyPropertyChanged(); } @@ -174,18 +176,18 @@ public string CurrentPaiement public AcompteViewModel AdherentPayer { get => adherentPayer; - set + set { adherentPayer = value; NotifyPropertyChanged(); - } + } } /// /// Permet d'afficher la sélection d'acompte /// - public bool ShowPayAcompte - { + public bool ShowPayAcompte + { get => showPayAcompte; set { @@ -206,11 +208,11 @@ public bool IsAdherent } } - public bool ShowPayPaypal - { + public bool ShowPayPaypal + { get => showPayPaypal; - set - { + set + { showPayPaypal = value; NotifyPropertyChanged(); } @@ -219,8 +221,8 @@ public bool ShowPayPaypal public bool ShowPayBanque { get => showPayBanque; - set - { + set + { showPayBanque = value; NotifyPropertyChanged(); } @@ -229,18 +231,18 @@ public bool ShowPayBanque public string PrixIHM { get { return prixIhm; } - set - { + set + { prixIhm = value; NotifyPropertyChanged(); } } - public bool ShowPayLiquide - { + public bool ShowPayLiquide + { get => showPayLiquide; - set - { + set + { showPayLiquide = value; NotifyPropertyChanged(); } @@ -251,6 +253,20 @@ public bool ShowPayLiquide #region methods + private record class InfosPaiementAcompte(AcompteViewModel acompte, float argent, float prix); + + private static string FindPaymentCodeFor(string paymentName) + { + return paymentName switch + { + "Acompte" => "Deposit", + "Paypal" => "Paypal", + "Carte" => "CreditCard", + "Liquide" => "Cash", + _ => throw new ArgumentException($"Méthode de paiement inconnue : « {paymentName} »") + }; + } + /// /// Permet de payer les articles /// @@ -258,15 +274,13 @@ private async void PayArticles(object tuple = null) { string messageLog = $"Achat par {currentPaiement} "; - // Paiement par acompte try { - if (tuple is Tuple values) + InfosPaiementAcompte? paiementAcompte = null; + + // Paiement par acompte + if (tuple is (AcompteViewModel acompte, bool isAdherentCheckboxChecked)) { - AcompteViewModel acompte = values.Item1; - bool isAdherentCheckboxChecked = values.Item2; - - float argent = ConverterFormatArgent.ConvertToDouble(acompte.ArgentIHM); float prix; if (isAdherentCheckboxChecked) { @@ -276,42 +290,60 @@ private async void PayArticles(object tuple = null) { prix = this.PriceNanAdher; } + paiementAcompte = new InfosPaiementAcompte( + acompte, + argent: ConverterFormatArgent.ConvertToDouble(acompte.ArgentIHM), + prix + ); - if (argent - prix < 0) + if (paiementAcompte.argent - prix < 0) { throw new Exception("Pas assez d'argent sur l'acompte"); } - _ = Task.Run(() => - { - StatAcompte stat = new StatAcompte(0, DateTime.Now, prix, acompte.Id); - MainWindowViewModel.Instance.StatViewModel.AddStatAcompte(stat); - statAcompteManager.CreateStat(stat); - }); - - string prixFormatted = ConverterFormatArgent.ConvertToString(prix); - acompte.ArgentIHM = ConverterFormatArgent.ConvertToString(argent - prix); - messageLog += $"{acompte.IdentifiantIHM} "; - messageLog += $"({prixFormatted}) : "; - acompte.UpdateAcompte(false); - + orderManager.NewOrder("Deposit", acompte.IdentifiantIHM); } else { if (isAdherent) { + orderManager.NewOrder( + FindPaymentCodeFor(currentPaiement), + Order.ANONYMOUS_MEMBER // le client est un adhérent, juste on sait pas qui + ); messageLog += $"({this.PriceAdherIHM}) : "; } else { + orderManager.NewOrder(FindPaymentCodeFor(currentPaiement)); messageLog += $"{this.PriceNonAdherIHM} : "; } } + foreach (var kvp in productOrder) + { + orderManager.CurrentOrder.AddProduct(kvp.Key.Id, kvp.Value); + messageLog += kvp.Key.NomProduitIHM + ", "; + } + + // Envoyer le paiement à l'API + orderManager.ProcessOrder(); - foreach (ProductViewModel product in productOrder.Keys) + // Terminer le paiment par acompte + if (paiementAcompte is InfosPaiementAcompte infos) { - messageLog += product.NomProduitIHM + ", "; + _ = Task.Run(() => + { + StatAcompte stat = new StatAcompte(0, DateTime.Now, infos.prix, infos.acompte.Id); + MainWindowViewModel.Instance.StatViewModel.AddStatAcompte(stat); + statAcompteManager.CreateStat(stat); + }); + + string prixFormatted = ConverterFormatArgent.ConvertToString(infos.prix); + infos.acompte.ArgentIHM = ConverterFormatArgent.ConvertToString(infos.argent - infos.prix); + messageLog += $"{infos.acompte.IdentifiantIHM} "; + messageLog += $"({prixFormatted}) : "; + infos.acompte.UpdateAcompte(false, false); } // Gérer les stats @@ -323,9 +355,6 @@ private async void PayArticles(object tuple = null) StatProduit stat = new StatProduit(0, DateTime.Now, productOrder2[product], product.Id); MainWindowViewModel.Instance.StatViewModel.AddStatProduit(stat); statProduitManager.CreateStat(stat); - - product.QuantiteIHM -= productOrder2[product]; - product.UpdateProduct(false); } }); @@ -341,7 +370,6 @@ private async void PayArticles(object tuple = null) catch (Exception ex) { MessageBox.Show(ex.Message); - } @@ -376,11 +404,11 @@ private void PreviewPayArticles() break; case "Liquide": PrixIHM = "Montant : " + (this.isAdherent ? this.PriceAdherIHM : this.PriceNonAdherIHM); - this.ShowPayLiquide=true; + this.ShowPayLiquide = true; break; } } - + } /// @@ -396,9 +424,9 @@ public void AddProduct(object product) if (produitIHM.QuantiteIHM - productOrder[produitIHM] > 0) { this.productOrder[produitIHM]++; - + } - + } else { diff --git a/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs b/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs index dfe8361..7a3a3be 100644 --- a/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/CategoryViewModel.cs @@ -108,7 +108,7 @@ public void UpdateCategory() { // Mise à jour data category.NomCategory = this.nomCat; - MessageBoxErrorHandler.Handle(()=> this.categoryManager.UpdateCategory(category)); + MessageBoxErrorHandler.DoesntThrow(()=> this.categoryManager.UpdateCategory(category)); } @@ -130,7 +130,7 @@ public void ResetCategory() public void DeleteCategory() { // Mise à jour data - if (MessageBoxErrorHandler.Handle(() => this.categoryManager.DeleteCategory(category))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.categoryManager.DeleteCategory(category))) { foreach (ProductViewModel prod in MainWindowViewModel.Instance.ProductViewModel.Products.ToList().FindAll(x => x.CategoryIHM == this)) { diff --git a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs index 5177ff9..7059060 100644 --- a/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/MainWindowViewModel.cs @@ -69,6 +69,7 @@ private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") private ProductManager productManager; private StatAcompteManager statAcompteManager; private StatProduitManager statProduitManager; + private OrderManager orderManager; #endregion #region events @@ -150,9 +151,10 @@ private MainWindowViewModel(MainWindow mainWindow) this.acompteManager = new AcompteManager(); this.statAcompteManager = new StatAcompteManager(); this.statProduitManager = new StatProduitManager(); + this.orderManager = new OrderManager(); this.adherentViewModel = new AcomptesViewModel(acompteManager); this.productViewModel = new ProductsViewModel(productManager); - this.caisseViewModel = new CaisseViewModel(this.statAcompteManager, this.statProduitManager); + this.caisseViewModel = new CaisseViewModel(this.statAcompteManager, this.statProduitManager, this.orderManager); this.statViewModel = new StatistiqueViewModel(productManager, acompteManager, statAcompteManager, statProduitManager); this.logsViewModel = new LogsViewModel(userManager, logManager); this.userViewModel = new UsersViewModel(this.userManager); diff --git a/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs b/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs index 4c8ad1a..f4b9917 100644 --- a/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/ProductViewModel.cs @@ -289,7 +289,7 @@ public void UpdateProduct(bool doLog = true) this.product.Categorie = this.categoryManager.ListAllCategory().Find(x => x.NomCategory == categoryIHM.NomCat).IdCat; this.product.PrixAdherent = ConverterFormatArgent.ConvertToDouble(this.prixAdherentIHM); this.product.PrixNonAdherent = ConverterFormatArgent.ConvertToDouble(this.prixNonAdherentIHM); - if (MessageBoxErrorHandler.Handle(() => this.productManager.UpdateProduct(this.product))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.productManager.UpdateProduct(this.product))) { // Notifier la vue @@ -315,7 +315,7 @@ public void UpdateProduct(bool doLog = true) public void DeleteProduct() { // Changer la data - if (MessageBoxErrorHandler.Handle(() => this.productManager.RemoveProduct(this.product))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.productManager.RemoveProduct(this.product))) { // Log l'action @@ -349,7 +349,7 @@ public void CreateProduct() this.product.PrixAdherent = ConverterFormatArgent.ConvertToDouble(this.prixAdherentIHM); this.product.PrixNonAdherent = ConverterFormatArgent.ConvertToDouble(this.prixNonAdherentIHM); - if (MessageBoxErrorHandler.Handle(() => this.productManager.CreateProduct(this.product))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.productManager.CreateProduct(this.product))) { this.action = "UPDATE"; diff --git a/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs b/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs index 259cb40..c9eac53 100644 --- a/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/ProductsViewModel.cs @@ -288,7 +288,7 @@ public void CreateCategory() { // Mise à jour data CategoryViewModel cat = new CategoryViewModel(this.categoryManager, new Category(0, "New", true)); - if (MessageBoxErrorHandler.Handle(() => this.categoryManager.CreateCategory(cat.Category))) + if (MessageBoxErrorHandler.DoesntThrow(() => this.categoryManager.CreateCategory(cat.Category))) { // Notifier la vue diff --git a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs index 7c77ce6..c982249 100644 --- a/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs +++ b/Couche IHM/Couche IHM/VueModeles/UserViewModel.cs @@ -174,21 +174,24 @@ public void UpdateUser() { this.user.HashedPassword = CryptString.Hash(this.mdpIHM2); } - this.userManager.UpdateCompte(this.user); - this.MdpIHM1 = ""; - this.MdpIHM2 = ""; - // Log l'action - Log log = new Log(DateTime.Now, 6, $"Modification du compte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + if (MessageBoxErrorHandler.DoesntThrow(() => this.userManager.UpdateCompte(this.user))) + { + this.MdpIHM1 = ""; + this.MdpIHM2 = ""; - // Notifier la vue - NotifyPropertyChanged(nameof(this.NomCompletIHM)); - NotifyPropertyChanged(nameof(this.NomIHM)); - NotifyPropertyChanged(nameof(this.PrenomIHM)); - NotifyPropertyChanged(nameof(this.EmailIHM)); - NotifyPropertyChanged(nameof(this.RoleIHM)); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + // Log l'action + Log log = new Log(DateTime.Now, 6, $"Modification du compte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); + + // Notifier la vue + NotifyPropertyChanged(nameof(this.NomCompletIHM)); + NotifyPropertyChanged(nameof(this.NomIHM)); + NotifyPropertyChanged(nameof(this.PrenomIHM)); + NotifyPropertyChanged(nameof(this.EmailIHM)); + NotifyPropertyChanged(nameof(this.RoleIHM)); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + } MainWindowViewModel.Instance.UserViewModel.ShowModifCreateUser = false; } else @@ -271,15 +274,16 @@ public void ResetUser() public void DeleteUser() { // Initialisation propriétés - this.userManager.RemoveCompte(this.user); - - // Log l'action - Log log = new Log(DateTime.Now, 6, $"Suppression du compte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); - MainWindowViewModel.Instance.LogManager.CreateLog(log); + if (MessageBoxErrorHandler.DoesntThrow(() => this.userManager.RemoveCompte(this.user))) + { + // Log l'action + Log log = new Log(DateTime.Now, 6, $"Suppression du compte : {this.NomCompletIHM}", MainWindowViewModel.Instance.CompteConnected.NomCompletIHM); + MainWindowViewModel.Instance.LogManager.CreateLog(log); - // Notifier la vue - MainWindowViewModel.Instance.UserViewModel.RemoveUser(this); - MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + // Notifier la vue + MainWindowViewModel.Instance.UserViewModel.RemoveUser(this); + MainWindowViewModel.Instance.LogsViewModel.AddLog(new LogViewModel(log)); + } MainWindowViewModel.Instance.UserViewModel.ShowModifCreateUser = false; ShowConfirmationDelete = false; } diff --git "a/Couche IHM/Couche M\303\251tier/Manager/OrderManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/OrderManager.cs" new file mode 100644 index 0000000..06c035f --- /dev/null +++ "b/Couche IHM/Couche M\303\251tier/Manager/OrderManager.cs" @@ -0,0 +1,41 @@ +using Couche_Data.Interfaces; +using DocumentFormat.OpenXml.Presentation; +using GalliumPlusApi.Dao; +using Modeles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Couche_Métier.Manager +{ + public class OrderManager + { + private IOrderDao dao; + private Order? currentOrder; + + public Order CurrentOrder => currentOrder!; + + public OrderManager() + { + dao = new OrderDao(); + } + + public void NewOrder(string paymentMethod, string customer = null) + { + currentOrder = new Order(paymentMethod, customer); + } + + public void ClearOrder() + { + currentOrder = null; + } + + public void ProcessOrder() + { + dao.ProcessOrder(currentOrder!); + ClearOrder(); + } + } +} diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" index 29d5120..6cb8ac6 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatAcompteManager.cs" @@ -25,15 +25,7 @@ public class StatAcompteManager /// public StatAcompteManager() { - try - { - dao = new Couche_Data.Dao.StatAcompteDAO(); - } - catch (Exception error) - { - Console.WriteLine("Impossible de se connecter à la base de donnée GV2 : " + error.Message); - dao = new GalliumPlusApi.Dao.StatAcompteDAO(); - } + dao = new Couche_Data.Dao.StatAcompteDAO(); this.statAcompteList = new List(); Task.Run(() => this.statAcompteList = dao.GetStat()); diff --git "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" index 113095b..af589cd 100644 --- "a/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" +++ "b/Couche IHM/Couche M\303\251tier/Manager/StatProduitManager.cs" @@ -24,16 +24,7 @@ public class StatProduitManager /// public StatProduitManager() { - - try - { - dao = new Couche_Data.Dao.StatProduitDAO(); - } - catch (Exception error) - { - Console.WriteLine("Impossible de se connecter à la base de donnée GV2 : " + error.Message); - dao = new GalliumPlusApi.Dao.StatProduitDAO(); - } + dao = new Couche_Data.Dao.StatProduitDAO(); statProduitList = new(); Task.Run(()=> statProduitList = dao.GetStat()); } diff --git a/Couche IHM/GalliumPlusApi/Dao/OrderDao.cs b/Couche IHM/GalliumPlusApi/Dao/OrderDao.cs new file mode 100644 index 0000000..28fa2ff --- /dev/null +++ b/Couche IHM/GalliumPlusApi/Dao/OrderDao.cs @@ -0,0 +1,19 @@ +using Couche_Data.Interfaces; +using GalliumPlusApi.Dto; +using Modeles; + +namespace GalliumPlusApi.Dao +{ + public class OrderDao : IOrderDao + { + private OrderSummary.Mapper mapper = new(); + + public void ProcessOrder(Order order) + { + using var client = new GalliumPlusHttpClient(); + client.UseSessionToken(SessionStorage.Current.Get("token")); + + client.Post($"v1/orders", mapper.FromModel(order)); + } + } +} diff --git a/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs b/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs deleted file mode 100644 index eb556f6..0000000 --- a/Couche IHM/GalliumPlusApi/Dao/StatAcompteDAO.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; - -namespace GalliumPlusApi.Dao -{ - public class StatAcompteDAO : IStatAcompteDAO - { - public void CreateStat(StatAcompte stat) - { - - } - - public List GetStat() - { - return new(); - } - } -} diff --git a/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs b/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs deleted file mode 100644 index 7bd452c..0000000 --- a/Couche IHM/GalliumPlusApi/Dao/StatProduitDAO.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Couche_Data.Interfaces; -using Modeles; - -namespace GalliumPlusApi.Dao -{ - public class StatProduitDAO : IStatProduitDAO - { - public void CreateStat(StatProduit stat) - { - - } - - public List GetStat() - { - return new(); - } - } -} diff --git a/Couche IHM/GalliumPlusApi/Dto/Error.cs b/Couche IHM/GalliumPlusApi/Dto/Error.cs index 107dd6c..d3583ca 100644 --- a/Couche IHM/GalliumPlusApi/Dto/Error.cs +++ b/Couche IHM/GalliumPlusApi/Dto/Error.cs @@ -19,7 +19,7 @@ public string DetailedMessage { StringBuilder sb = new(); sb.Append(Message); - +#if DEBUG if (DebugInfo != null) { sb.Append("\n\nInformations de débogage:\n"); @@ -29,6 +29,7 @@ public string DetailedMessage { sb.Append("\n\nAucune informations de débogage."); } +#endif return sb.ToString(); } } diff --git a/Couche IHM/GalliumPlusApi/Dto/Mapper.cs b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs index b67ca31..fda55f4 100644 --- a/Couche IHM/GalliumPlusApi/Dto/Mapper.cs +++ b/Couche IHM/GalliumPlusApi/Dto/Mapper.cs @@ -16,5 +16,10 @@ public virtual TDto FromModel(TModel model) { throw new InvalidOperationException("Ce DTO ne doit pas sortir !! >:("); } + + public IEnumerable FromModel(IEnumerable models) + { + foreach (TModel model in models) yield return FromModel(model); + } } } diff --git a/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs b/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs index 50da478..6360969 100644 --- a/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/OrderItemSummary.cs @@ -1,34 +1,16 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Orders; -using System.ComponentModel.DataAnnotations; - -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class OrderItemSummary { - [Required] public int? Product { get; set; } - [Required] public int? Quantity { get; set; } + public int Product { get; set; } + public int Quantity { get; set; } - public class Mapper : Mapper + public class Mapper : Mapper, OrderItemSummary> { - private IProductDao productDao; - - public Mapper(IProductDao productDao) - { - this.productDao = productDao; - } - - public override OrderItemSummary FromModel(OrderItem model) - { - // ne sort jamais du serveur ! - throw new NotImplementedException(); - } - - public override OrderItem ToModel(OrderItemSummary dto) + public override OrderItemSummary FromModel(KeyValuePair model) { - return new OrderItem(this.productDao.Read(dto.Product!.Value), dto.Quantity!.Value); + return new OrderItemSummary { Product = model.Key, Quantity = model.Value }; } } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs b/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs index 056f138..899d3e7 100644 --- a/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs +++ b/Couche IHM/GalliumPlusApi/Dto/OrderSummary.cs @@ -1,83 +1,26 @@ -/*using GalliumPlus.WebApi.Core.Data; -using GalliumPlus.WebApi.Core.Exceptions; -using GalliumPlus.WebApi.Core.Orders; -using GalliumPlus.WebApi.Core.Users; -using System.ComponentModel.DataAnnotations; +using Modeles; -namespace GalliumPlus.WebApi.Dto +namespace GalliumPlusApi.Dto { public class OrderSummary { - [Required] public string PaymentMethod { get; set; } + public string PaymentMethod { get; set; } = String.Empty; public string? Customer { get; set; } - [Required] public List? Items { get; set; } - - public OrderSummary() - { - PaymentMethod = String.Empty; - Items = null; - } + public List Items { get; set; } = new(); public class Mapper : Mapper { - private OrderItemSummary.Mapper orderItemMapper; - private IUserDao userDao; - - public Mapper(IUserDao userDao, IProductDao productDao) - { - this.userDao = userDao; - this.orderItemMapper = new(productDao); - } + private OrderItemSummary.Mapper orderItemMapper = new(); public override OrderSummary FromModel(Order model) { - // ne sort jamais du serveur ! - throw new NotImplementedException(); - } - - public override Order ToModel(OrderSummary dto) - { - PaymentMethodFactory factory = new(this.userDao); - - User? customer; - if (dto.Customer == null) - { - customer = null; - } - else if (dto.Customer == Order.ANONYMOUS_MEMBER_ID) - { - customer = BuildAnonymousMember(); - } - else + return new OrderSummary { - try - { - customer = this.userDao.Read(dto.Customer); - } - catch (ItemNotFoundException) - { - throw new InvalidItemException($"L'utilisateur « {dto.Customer} » n'existe pas"); - } - } - - return new Order( - factory.Create(dto.PaymentMethod, dto.Customer), - dto.Items!.Select(saleItemDto => this.orderItemMapper.ToModel(saleItemDto)), - customer - ); - } - - private static User BuildAnonymousMember() - { - return new User( - "anonymousmember00000000000", // pas possible d'être rentré en BDD - new UserIdentity("Anonyme", "", "", ""), - new Role(-1, "Membre anonyme", Permissions.NONE), - 0.00m, - false - ); + Customer = model.Customer, + PaymentMethod = model.PaymentMethod, + Items = orderItemMapper.FromModel(model.OrderedProducts).ToList(), + }; } } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/Couche IHM/Modeles/Category.cs b/Couche IHM/Modeles/Category.cs index c1cc2e4..7a85f96 100644 --- a/Couche IHM/Modeles/Category.cs +++ b/Couche IHM/Modeles/Category.cs @@ -1,5 +1,4 @@ - -namespace Modeles +namespace Modeles { public class Category { diff --git a/Couche IHM/Modeles/Order.cs b/Couche IHM/Modeles/Order.cs new file mode 100644 index 0000000..2f9dc22 --- /dev/null +++ b/Couche IHM/Modeles/Order.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Modeles +{ + public class Order + { + private Dictionary orderedProducts; + private string? customer; + private string paymentMethod; + + public static readonly string ANONYMOUS_MEMBER = "@anonymousmember"; + + public IDictionary OrderedProducts => orderedProducts; + + public string? Customer => customer; + + public string PaymentMethod => paymentMethod; + + public Order(string paymentMethod, string? customer = null) + { + this.paymentMethod = paymentMethod; + this.customer = customer; + orderedProducts = new Dictionary(); + } + + public void AddProduct(int productId, int quantity) + { + orderedProducts[productId] = quantity; + } + } +} From 1d23f0f512ba301551e338daa75f826832aa56b2 Mon Sep 17 00:00:00 2001 From: Louis Devie Date: Tue, 31 Oct 2023 17:51:18 +0100 Subject: [PATCH 09/56] Remettre en place les contraintes de nom d'utilisateur --- .../Couche IHM/BindingRules/RuleIDFormat.cs | 25 ++++++++----------- .../Couche IHM/Frames/FrameAcompte.xaml | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs b/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs index e4c5c5f..3970cab 100644 --- a/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs +++ b/Couche IHM/Couche IHM/BindingRules/RuleIDFormat.cs @@ -27,28 +27,23 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo) AcompteViewModel adh = MainWindowViewModel.Instance.AdherentViewModel.CurrentAcompte; string identifiant = (string)value; - if (identifiant.Length == 0) + if (identifiant.Length > 2) { - result = new ValidationResult(false, "Veuillez saisir un nom d'utilisateur"); - } - else if (identifiant.Length > 20) - { - result = new ValidationResult(false, "Un nom d'utilisateur ne peut pas dépasser 20 caractères"); + string nom = adh.NomIHM; + string prenom = adh.PrenomIHM; + if (identifiant[0] != prenom.ToLower()[0] || identifiant[1] != nom.ToLower()[0]) + { + result = new ValidationResult(false, "Format invalide"); + } } else { - if (identifiant.Any(c => !IsAsciiAndLowerCaseLetterOrDigit(c))) - { - result = new ValidationResult(false, "Un nom d'utilisateur doit comprendre uniquement des lettre minuscules et des chiffres"); - } + result = new ValidationResult(false, "Format invalide"); } + + return result; } - - private static bool IsAsciiAndLowerCaseLetterOrDigit(char c) - { - return char.IsAscii(c) && (char.IsLower(c) || char.IsDigit(c)); - } } } diff --git a/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml b/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml index 0f37493..3d84a73 100644 --- a/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml +++ b/Couche IHM/Couche IHM/Frames/FrameAcompte.xaml @@ -463,7 +463,7 @@ Margin="20,20,20,10" materialDesign:HintAssist.Hint="Identifiant de l'acompte" Style="{StaticResource MaterialDesignFilledTextBox}" - MaxLength="20"> + MaxLength="8"> Date: Tue, 31 Oct 2023 18:14:30 +0100 Subject: [PATCH 10/56] Fix IHM suite au merge --- Couche IHM/Couche IHM/Frames/FrameCaisse.xaml | 48 ++++++++----------- .../Couche IHM/Frames/FrameComptes.xaml | 14 ++---- Couche IHM/Couche IHM/MainWindow.xaml | 10 +--- 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/Couche IHM/Couche IHM/Frames/FrameCaisse.xaml b/Couche IHM/Couche IHM/Frames/FrameCaisse.xaml index 01038c6..8d630b8 100644 --- a/Couche IHM/Couche IHM/Frames/FrameCaisse.xaml +++ b/Couche IHM/Couche IHM/Frames/FrameCaisse.xaml @@ -12,7 +12,7 @@ - + @@ -20,19 +20,19 @@ - + - + - + @@ -42,7 +42,7 @@ FontWeight="Medium" FontFamily="Roboto" Content="Panier" - FontSize="15" + FontSize="18" Foreground="#FF403D39"/> @@ -117,37 +119,34 @@ - + - - +