First Commit

This commit is contained in:
Maxime Boulay 2024-12-23 08:05:29 +01:00
commit ba64ceb471
171 changed files with 654157 additions and 0 deletions

BIN
backend/.DS_Store vendored Normal file

Binary file not shown.

4
backend/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
GiecChallenge/bin/
GiecChallenge/obj/
GiecChallenge.test/bin/
GiecChallenge.test/obj/

33
backend/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/GiecChallenge/bin/Debug/net7.0/GiecChallenge.dll",
"args": [],
"cwd": "${workspaceFolder}/GiecChallenge",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

41
backend/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/GiecChallenge/GiecChallenge.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/GiecChallenge/GiecChallenge.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/GiecChallenge/GiecChallenge.csproj"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -0,0 +1,886 @@
using Moq;
using Microsoft.EntityFrameworkCore;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Text;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
namespace GiecChallenge.Tests
{
public static class Common
{
public static Mock<GiecChallengeContext> GetContext() {
var options = new DbContextOptionsBuilder<GiecChallengeContext>()
.UseInMemoryDatabase(databaseName: "GiecChallengeContext")
.Options;
Mock<GiecChallengeContext> dataContext = new Mock<GiecChallengeContext>(options);
dataContext.Setup(m => m.AddAsync(It.IsAny<Aliment>(), It.IsAny<CancellationToken>())).Callback<Aliment, CancellationToken>((s, token) =>
{
Common.GetAliments().Add(s);
});
dataContext.Setup(c => c.SaveChangesAsync(default))
.Returns(Task.FromResult(1))
.Verifiable();
return dataContext;
}
public static Mock<DbSet<T>> GetMockDbSet<T>(List<T> objectList) where T : class
{
var objectQueryable = objectList.AsQueryable();
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IAsyncEnumerable<T>>()
.Setup(m => m.GetAsyncEnumerator(default(CancellationToken)))
.Returns(new AsyncEnumeratorWrapper<T>(objectQueryable.GetEnumerator()));
mockSet.As<IQueryable<T>>()
.Setup(m => m.Provider)
.Returns(new AsyncQueryProvider<T>(objectQueryable.Provider));
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(objectQueryable.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(objectQueryable.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => objectQueryable.GetEnumerator());
mockSet.Setup(m => m.AddAsync(It.IsAny<T>(), default)).Callback<T, CancellationToken>((s, token) => { objectList.Add(s); });
return mockSet;
}
#region Aliments
public static List<AlimentDto> GetAlimentDto() {
return new List<AlimentDto>() {
new AlimentDto() { nom_francais = "tomate", ciqual_code = "1002", impact_environnemental = new ImpactEnvironnementalAlimentDto() { changement_climatique = new ChangementClimatiqueDto() { synthese = 3, unite = "l" }, epuisement_eau = new EpuisementEauDto() { synthese = 15, unite = "kg" }}},
new AlimentDto() { nom_francais = "poireau", ciqual_code = "1003", impact_environnemental = new ImpactEnvironnementalAlimentDto() { changement_climatique = new ChangementClimatiqueDto() { synthese = 4, unite = "l" }, epuisement_eau = new EpuisementEauDto() { synthese = 0.15, unite = "kg" }}},
new AlimentDto() { nom_francais = "chou", ciqual_code = "1004", impact_environnemental = new ImpactEnvironnementalAlimentDto() { changement_climatique = new ChangementClimatiqueDto() { synthese = 5, unite = "l" }, epuisement_eau = new EpuisementEauDto() { synthese = 0.015, unite = "kg" }}}
};
}
public static List<Aliment> GetAliments() {
return new List<Aliment>() {
new Aliment() {
id = Guid.Parse("aac1d6b7-4ef7-4fff-bd6f-9acce73b671b"),
ciqual = "1002",
subgroup = GetProductSubGroup().First(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("5ece3218-cc5d-4a13-bece-2e62b0a6ca06"),
language = GetLanguages().First(),
name = "tomate"
},
new ProductLanguage() {
id = Guid.Parse("f02f5cf5-3e6d-407f-84cb-68deb7361c54"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "tomato"
}
},
CO2 = 0.62369712,
CO2Unit = "kg CO2 eq/kg de produit",
water = 2.3763367,
waterUnit = "m3 depriv./kg de produit"
},
new Aliment() {
id = Guid.Parse("ba0091db-4ce3-402e-b382-dbd2a8f4bfa4"),
ciqual = "1003",
subgroup = GetProductSubGroup().First(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("2e8507f4-213e-482f-b8d0-94647ee8b155"),
language = GetLanguages().First(),
name = "chou vert"
},
new ProductLanguage() {
id = Guid.Parse("eeb5a793-33b4-4524-b84a-5c71c9a67253"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "green sprout"
}
},
CO2 = 2.0557422,
CO2Unit = "kg CO2 eq/kg de produit",
water = 0.58653066,
waterUnit = "m3 depriv./kg de produit"
},
new Aliment() {
id = Guid.Parse("0a5fae36-10b3-46d2-84af-8ce174ec64f3"),
ciqual = "1004",
subgroup = GetProductSubGroup().First(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("60113b02-c446-4254-8614-fde7984fe2d7"),
language = GetLanguages().First(),
name = "Poireau"
},
new ProductLanguage() {
id = Guid.Parse("bce6224d-efd6-4c9b-97f2-182cb0d91515"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Leek"
}
},
CO2 = 0.71433485,
CO2Unit = "kg CO2 eq/kg de produit",
water = 1.8527791,
waterUnit = "m3 depriv./kg de produit"
}
};
}
public static Aliment GetAlimentTest(string name, string ciqual) {
return new Aliment() {
id = Guid.NewGuid(),
ciqual = ciqual,
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.NewGuid(),
language = GetLanguages().First(),
name = name
},
new ProductLanguage() {
id = Guid.NewGuid(),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = name
}
},
CO2 = 0.62369712,
CO2Unit = "kg CO2 eq/kg de produit",
water = 2.3763367,
waterUnit = "m3 depriv./kg de produit"
};
}
public static AlimentDto GetAlimentDtoTest(string name, string ciqual) {
return new AlimentDto() {
nom_francais = name,
ciqual_code = ciqual,
groupe = GetProductSubGroup().First().names.First().name,
impact_environnemental = new ImpactEnvironnementalAlimentDto() {
changement_climatique = new ChangementClimatiqueDto() {
synthese = 5,
unite = "l"
},
epuisement_eau = new EpuisementEauDto() {
synthese = 0.015,
unite = "kg"
}
}
};
}
#endregion
#region Products
public static List<ProductDto> GetProductsDto() {
return new List<ProductDto>() {
new ProductDto() {
names = new List<ProductNamesDto>() {
new ProductNamesDto() {
name = "iPad",
language = "EN"
},
new ProductNamesDto() {
name = "iPad",
language = "FR"
}
},
language = "FR",
group = "Tablette",
CO2 = 52,
CO2Unit = "kg CO2 eq/kg de produit",
water = 22.3763367,
waterUnit = "m3 depriv./kg de produit",
amortization = 48
},
new ProductDto() {
names = new List<ProductNamesDto>() {
new ProductNamesDto() {
name = "Pen",
language = "EN"
},
new ProductNamesDto() {
name = "Stylo",
language = "FR"
}
},
language = "FR",
group = "Papeterie",
CO2 = 0.005,
CO2Unit = "kg CO2 eq/kg de produit",
water = 0.25,
waterUnit = "m3 depriv./kg de produit",
amortization = 0
},
new ProductDto() {
names = new List<ProductNamesDto>() {
new ProductNamesDto() {
name = "Gas car",
language = "EN"
},
new ProductNamesDto() {
name = "Voiture thermique",
language = "FR"
}
},
language = "FR",
group = "Locomotion",
CO2 = 520000,
CO2Unit = "kg CO2 eq/kg de produit",
water = 16161.548,
waterUnit = "m3 depriv./kg de produit",
amortization = 180
},
};
}
public static List<Product> GetProducts() {
return new List<Product>() {
new Product() {
id = Guid.Parse("e5f89b1d-171f-4460-a2cc-18e1534b5bae"),
subgroup = GetProductSubGroup().Last(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("6380098e-fc8e-455a-94df-2635e4245d25"),
language = GetLanguages().First(),
name = "iPad"
},
new ProductLanguage() {
id = Guid.Parse("aa930251-be87-4d56-b132-f7d3b7c1b1a6"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "iPad"
}
},
amortization = 48,
CO2 = 0.62369712,
CO2Unit = "kg CO2 eq/kg de produit",
water = 2.3763367,
waterUnit = "m3 depriv./kg de produit"
},
new Product() {
id = Guid.Parse("526ea756-50da-486f-8a44-5e964f249c1e"),
subgroup = GetProductSubGroup().First(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("0da29478-8b97-4224-b99b-e3bb8895301d"),
language = GetLanguages().First(),
name = "chou vert"
},
new ProductLanguage() {
id = Guid.Parse("9ff4dab7-8fe6-4147-9edf-e8bda65a5f9d"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "green sprout"
}
},
CO2 = 2.0557422,
CO2Unit = "kg CO2 eq/kg de produit",
water = 0.58653066,
waterUnit = "m3 depriv./kg de produit"
},
new Product() {
id = Guid.Parse("fb3ee25c-b3a4-4b80-a14e-9a1a8093554d"),
subgroup = GetProductSubGroup().First(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("41049c06-f3e1-4744-8958-dc3f9b1c172d"),
language = GetLanguages().First(),
name = "Stylo"
},
new ProductLanguage() {
id = Guid.Parse("f46b47bb-bc9a-4563-82ae-40a73777464d"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Pen"
}
},
CO2 = 0.71433485,
CO2Unit = "kg CO2 eq/kg de produit",
water = 1.8527791,
waterUnit = "m3 depriv./kg de produit"
}
};
}
public static Product GetProductTest(string name, Guid id) {
return new Product() {
id = Guid.NewGuid(),
names = new List<ProductLanguage>() {
new ProductLanguage() {
id = Guid.Parse("fe7ebeb5-11b6-4c4f-8ab3-e02e663f553a"),
language = GetLanguages().First(),
name = name
},
new ProductLanguage() {
id = Guid.Parse("2185d186-1676-42ca-a444-f05884b5d4fd"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = name
}
},
CO2 = 0.62369712,
CO2Unit = "kg CO2 eq/kg de produit",
water = 2.3763367,
waterUnit = "m3 depriv./kg de produit"
};
}
public static ProductDto GetProductDtoTest(string name, string group, string language) {
return new ProductDto() {
names = new List<ProductNamesDto>() {
new ProductNamesDto() {
name = name,
language = language
},
new ProductNamesDto() {
name = name,
language = "f3390acd-acf2-4ab9-8d39-25b216182320"
}
},
language = language,
group = group,
CO2 = 31,
CO2Unit = "kg CO2 eq/kg de produit",
water = 2.3763367,
waterUnit = "m3 depriv./kg de produit",
amortization = 48
};
}
public static ProductUserTranslationDTO GetProductTranslationDtoTest(string name, string user, string product, string id) {
return new ProductUserTranslationDTO() {
user = user,
product = product,
name = name,
id = id
};
}
public static List<ProductUserTranslation> GetProductUserTranslations() {
return new List<ProductUserTranslation>() {
new ProductUserTranslation() {
id = Guid.Parse("479d91d4-8f93-433f-8b4c-b5b08c12db5c"),
user = GetUsers().First(),
product = GetProducts().First(),
name = "tomate de saison"
},
new ProductUserTranslation() {
id = Guid.Parse("5823ec98-2726-4b39-b01e-8453bbde5524"),
user = GetUsers().First(u => u.email == "toto1@toto.com"),
product = GetProducts().First(p => p.id == Guid.Parse("526ea756-50da-486f-8a44-5e964f249c1e")),
name = "chou de saison"
}
};
}
#endregion
#region Language
public static List<Language> GetLanguages() {
var languages = new List<Language>() {
new Language() {
id = Guid.Parse("f3390acd-acf2-4ab9-8d39-25b216182320"),
ISOCode = "FR"
},
new Language() {
id = Guid.Parse("0b1307be-9ffd-4dcd-9431-4fe58b6420f7"),
ISOCode = "EN"
},
new Language() {
id = Guid.Parse("d7ee9249-1edc-4158-ad4d-9892fb703e47"),
ISOCode = "DE"
}
};
languages.First().names = new List<LanguageLanguage>() {
new LanguageLanguage() {
id = Guid.Parse("aab43c46-b2c9-4b7f-bc1f-9b93690b7ffb"),
language = languages.First(),
languageToChange = languages.First(),
name = "Français"
},
new LanguageLanguage() {
id = Guid.Parse("c5ef4000-6bf6-4206-af78-edecd622b43b"),
language = languages.First(l => l.ISOCode == "EN"),
languageToChange = languages.First(),
name = "French"
}
};
languages.First(l => l.ISOCode == "EN").names = new List<LanguageLanguage>() {
new LanguageLanguage() {
id = Guid.Parse("f28163fd-ffc6-4da9-beed-2367ee4e2c9e"),
language = languages.First(),
languageToChange = languages.First(l => l.ISOCode == "EN"),
name = "Anglais"
},
new LanguageLanguage() {
id = Guid.Parse("190f992f-b2bc-44a2-a062-0129088d557a"),
language = languages.First(l => l.ISOCode == "EN"),
languageToChange = languages.First(l => l.ISOCode == "EN"),
name = "English"
}
};
languages.Last().names = new List<LanguageLanguage>() {
new LanguageLanguage() {
id = Guid.Parse("d8ea2692-dbf4-467e-b767-b0187f333775"),
language = languages.First(),
languageToChange = languages.Last(),
name = "Allemand"
}
};
return languages;
}
public static List<LanguageDto> GetLanguagesDto(string nameFR, string nameEN) {
return new List<LanguageDto>() {
new LanguageDto() {
ISOCode = "FR",
names = new List<LanguageNamesDto>() {
new LanguageNamesDto() {
name = nameFR,
language = "EN"
},
new LanguageNamesDto() {
name = nameFR,
language = "FR"
}
}
},
new LanguageDto() {
ISOCode = "EN",
names = new List<LanguageNamesDto>() {
new LanguageNamesDto() {
name = nameEN,
language = "EN"
},
new LanguageNamesDto() {
name = nameEN,
language = "FR"
}
}
}
};
}
public static LanguageDto GetLanguageDtoTest(string ISOCode, string name, string language = "FR") {
return new LanguageDto() {
ISOCode = ISOCode,
names = new List<LanguageNamesDto>() {
new LanguageNamesDto() {
name = name,
language = language
}
}
};
}
#endregion
#region Group
public static List<ProductGroup> GetProductGroup() {
return new List<ProductGroup>() {
new ProductGroup() {
id = Guid.Parse("991979cd-b95f-4e9a-85e7-e1f7ce6932fb"),
names = new List<ProductGroupLanguage>() {
new ProductGroupLanguage() {
id = Guid.Parse("6d5b7831-c61d-4923-820d-9bde93dd2723"),
language = GetLanguages().First(l => l.ISOCode == "FR"),
name = "Aliment"
},
new ProductGroupLanguage() {
id = Guid.Parse("092f0c65-9bdd-46a3-81f0-2c521b34596e"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Food"
}
}
},
new ProductGroup() {
id = Guid.Parse("3a69d206-7236-11ed-a1eb-0242ac120002"),
names = new List<ProductGroupLanguage>() {
new ProductGroupLanguage() {
id = Guid.Parse("3a69d4c2-7236-11ed-a1eb-0242ac120002"),
language = GetLanguages().First(l => l.ISOCode == "FR"),
name = "Éléctronique"
},
new ProductGroupLanguage() {
id = Guid.Parse("3a69d8b4-7236-11ed-a1eb-0242ac120002"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Electronic devices"
}
}
}
};
}
public static List<ProductGroup> GetGroups() {
return new List<ProductGroup>() {
new ProductGroup() {
id = Guid.Parse("b21a6403-f428-454f-942d-dbd1fc3fa551"),
names = new List<ProductGroupLanguage>() {
GetGroupLanguage().First(),
GetGroupLanguage().First(gpl => gpl.name == "Food"),
}
},
new ProductGroup() {
id = Guid.Parse("8f46bf6f-6cbf-47ac-8d51-039eabc820c3"),
names = new List<ProductGroupLanguage>() {
GetGroupLanguage().Last()
}
}
};
}
public static List<ProductGroupLanguage> GetGroupLanguage() {
return new List<ProductGroupLanguage>() {
new ProductGroupLanguage() {
id = Guid.Parse("fae75424-d098-43fd-97ca-296da57501c2"),
language = GetLanguages().First(),
name = "Aliment"
},
new ProductGroupLanguage() {
id = Guid.Parse("fc394591-5b8b-4493-9d40-fc6a1a25b0c7"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Food"
},
new ProductGroupLanguage() {
id = Guid.Parse("b615e2d8-ebc1-4b2b-a2fd-0bab9449278e"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Electronic device"
}
};
}
public static List<GroupDto> GetGroupsDto(string nameFR, string nameEN) {
return new List<GroupDto>() {
new GroupDto() {
id = Guid.Parse("b21a6403-f428-454f-942d-dbd1fc3fa551"),
names = new List<GroupNamesDto>() {
new GroupNamesDto() {
name = nameFR,
language = "EN"
},
new GroupNamesDto() {
name = nameFR,
language = "FR"
}
}
},
new GroupDto() {
id = Guid.Parse("8f46bf6f-6cbf-47ac-8d51-039eabc820c3"),
names = new List<GroupNamesDto>() {
new GroupNamesDto() {
name = nameEN,
language = "EN"
},
new GroupNamesDto() {
name = nameEN,
language = "FR"
}
}
}
};
}
public static GroupDto GetGroupDtoTest(string name, string language = "FR") {
return new GroupDto() {
names = new List<GroupNamesDto>() {
new GroupNamesDto() {
name = name,
language = language
}
}
};
}
#endregion
#region SubGroup
public static List<ProductSubGroup> GetProductSubGroup() {
return new List<ProductSubGroup>() {
new ProductSubGroup() {
id = Guid.Parse("4f52f771-7752-472f-921e-88824fc4c5d5"),
names = new List<ProductSubGroupLanguage>() {
new ProductSubGroupLanguage() {
id = Guid.Parse("9a43209f-9a7e-4890-94fc-3c8d8d26a614"),
language = GetLanguages().First(l => l.ISOCode == "FR"),
name = "Boisson"
},
new ProductSubGroupLanguage() {
id = Guid.Parse("698c1cd6-66c9-45b8-95e7-da65da4772c0"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Beverage"
}
},
Groupe = GetProductGroup().First()
},
new ProductSubGroup() {
id = Guid.Parse("04f3eb50-6119-487a-86a6-b6c24e620536"),
names = new List<ProductSubGroupLanguage>() {
new ProductSubGroupLanguage() {
id = Guid.Parse("f2a3ed11-7205-46e8-b1b2-911db83bbe90"),
language = GetLanguages().First(l => l.ISOCode == "FR"),
name = "Téléphone portable"
},
new ProductSubGroupLanguage() {
id = Guid.Parse("300416ca-9a76-4f1b-9b98-7742b0f93098"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Smartphone"
}
},
Groupe = GetProductGroup().Last()
}
};
}
public static List<ProductSubGroup> GetSubGroups() {
return new List<ProductSubGroup>() {
new ProductSubGroup() {
id = Guid.Parse("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32"),
names = new List<ProductSubGroupLanguage>() {
GetSubGroupLanguage().First(),
GetSubGroupLanguage().First(sgl => sgl.id == Guid.Parse("a4b8abef-fd9d-4695-b8d6-8bbc005bf596"))
},
Groupe = GetGroups().First()
},
new ProductSubGroup() {
id = Guid.Parse("1dda078c-d158-4078-aa8e-981d5ac5cd57"),
names = new List<ProductSubGroupLanguage>() {
GetSubGroupLanguage().Last()
} ,
Groupe = GetGroups().Last()
}
};
}
public static List<ProductSubGroupLanguage> GetSubGroupLanguage() {
return new List<ProductSubGroupLanguage>() {
new ProductSubGroupLanguage() {
id = Guid.Parse("b713e22b-a4c1-4b57-8135-9f3ab0c7b760"),
language = GetLanguages().First(),
name = "Boisson"
},
new ProductSubGroupLanguage() {
id = Guid.Parse("a4b8abef-fd9d-4695-b8d6-8bbc005bf596"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Drink"
},
new ProductSubGroupLanguage() {
id = Guid.Parse("bf5f66ea-9cca-41ee-b4be-1d9a9f6a450c"),
language = GetLanguages().First(l => l.ISOCode == "EN"),
name = "Smartphone"
}
};
}
public static SubGroupDto GetSubGroupDtoTest(string name, string groupName, string language = "FR") {
return new SubGroupDto() {
names = new List<SubGroupNamesDto>() {
new SubGroupNamesDto() {
name = name,
language = language
}
},
language = language,
group = groupName
};
}
#endregion
#region Users
public static UserDto GetUserDto(string email, string password, string language) {
return new UserDto() {
email = email,
password = password,
language = language
};
}
public static List<User> GetUsers() {
return new List<User>() {
new User() {
id = Guid.Parse("0a891394-be17-473b-9924-eccaf6ce79ed"),
email = "toto@toto.com",
password = EncryptPassword("password1", Encoding.ASCII.GetBytes("hYHDi5p23oOzZQVSyMUAanvYFtBhpFgYPwpkfs5iVEs=")),
hash = Encoding.ASCII.GetBytes("hYHDi5p23oOzZQVSyMUAanvYFtBhpFgYPwpkfs5iVEs="),
creationDate = DateTime.Now,
favoriteLanguage = GetLanguages().First()
},
new User() {
id = Guid.Parse("9beb47ab-0def-437c-b510-02d8f9623ebb"),
email = "toto1@toto.com",
password = EncryptPassword("password2", Encoding.ASCII.GetBytes("NBLjPomVm3HeIRetpgDzavp3axIKNJQKa85XY8KJ1zY=")),
hash = Encoding.ASCII.GetBytes("NBLjPomVm3HeIRetpgDzavp3axIKNJQKa85XY8KJ1zY="),
creationDate = DateTime.Now,
favoriteLanguage = GetLanguages().First(l => l.ISOCode == "EN")
}
};
}
public static List<UserGroup> GetUserGroups() {
return new List<UserGroup>() {
new UserGroup() {
id = Guid.Parse("eb3641a9-84c3-4d38-b350-925f58b04506"),
name = "Classic"
},
new UserGroup() {
id = Guid.Parse("bebf7ca6-27a7-47de-affe-ca7f5536ad96"),
name = "Admin"
}
};
}
#endregion
#region Purchase
public static PurchaseDto GetPurchaseDto(DateTime date, List<string> products, List<string> currencies, List<double> prices, List<double> quantities) {
return new PurchaseDto() {
datePurchase = date,
products = GetProductPurchaseDto(products, currencies, prices, quantities)
};
}
public static List<ProductPurchaseDto> GetProductPurchaseDto(List<string> products, List<string> currencies, List<double> prices, List<double> quantities) {
List<ProductPurchaseDto> purchases = new List<ProductPurchaseDto>();
if (products.Count != currencies.Count && currencies.Count != prices.Count)
throw new Exception("Tab must have the same length");
int i = 0;
foreach(string product in products) {
purchases.Add(new ProductPurchaseDto() {
product = product,
currencyIsoCode = currencies[i],
price = prices[i],
quantity = quantities[i]
});
i++;
}
return purchases;
}
public static List<CarbonLoan> GetCarbonLoans() {
return new List<CarbonLoan>() {
new CarbonLoan() {
id = Guid.Parse("d7205c76-a159-11ed-a8fc-0242ac120002"),
user = GetUsers().First(),
productPurchase = GetProductPurchases().First(),
dateBegin = GetProductPurchases().First().purchase.datePurchase,
dateEnd = GetProductPurchases().First().purchase.datePurchase.AddMonths(GetProductPurchases().First().product.amortization)
}
};
}
public static List<Purchase> GetPurchases() {
return new List<Purchase>() {
new Purchase() {
id = Guid.Parse("e2075166-6f2c-4172-8906-2f100a6a1456"),
datePurchase = DateTime.Parse("03/01/2022"),
user = GetUsers().First(),
products = new List<ProductPurchase>() {
GetProductPurchases().First(pp => pp.id == Guid.Parse("788b7e57-9b59-43ce-af8e-2d097551e442"))
}
},
new Purchase() {
id = Guid.Parse("b516e589-a039-4ce0-b6be-75bfc08cf6d3"),
datePurchase = DateTime.Parse("01/01/2022"),
user = GetUsers().First(),
products = new List<ProductPurchase>() {
GetProductPurchases().First(pp => pp.id == Guid.Parse("869a7030-f400-4b1b-aa12-e9245f791d0a")),
GetProductPurchases().First(pp => pp.id == Guid.Parse("32ed916c-6161-4565-8c8a-40a3e262bd40"))
}
},
new Purchase() {
id = Guid.Parse("51e6eec0-d9fd-47fc-830a-88d1e6638b88"),
datePurchase = DateTime.Parse("03/01/2022"),
user = GetUsers().Last(),
products = new List<ProductPurchase>() {
GetProductPurchases().First(pp => pp.id == Guid.Parse("bb4179dc-c18e-4576-b9f6-12e8c9f6456f"))
}
},
};
}
public static List<ProductPurchase> GetProductPurchases() {
return new List<ProductPurchase>() {
new ProductPurchase() {
id = Guid.Parse("788b7e57-9b59-43ce-af8e-2d097551e442"),
product = GetProducts().First(),
currency = GetCurrencies().First(),
price = 10
},
new ProductPurchase() {
id = Guid.Parse("869a7030-f400-4b1b-aa12-e9245f791d0a"),
product = GetProducts().First(),
currency = GetCurrencies().First(),
price = 10
},
new ProductPurchase() {
id = Guid.Parse("32ed916c-6161-4565-8c8a-40a3e262bd40"),
product = GetProducts().Last(),
currency = GetCurrencies().First(),
price = 15
},
new ProductPurchase() {
id = Guid.Parse("bb4179dc-c18e-4576-b9f6-12e8c9f6456f"),
product = GetProducts().First(),
currency = GetCurrencies().Last(),
price = 100
}
};
}
public static List<Currency> GetCurrencies() {
return new List<Currency>() {
new Currency() {
id = Guid.Parse("1a7d6616-dfd1-47c8-ba42-2b12e71c43af"),
ISOCode = "USD"
},
new Currency() {
id = Guid.Parse("a408c030-1b87-41bc-ad63-378e93f3780f"),
ISOCode = "EUR"
},
new Currency() {
id = Guid.Parse("2b4d7ecd-6ec3-439c-8984-e657a9bcc9c2"),
ISOCode = "CHF"
}
};
}
public static PurchaseLaRucheDto GetPurchaseLaRucheDto(DateTime date, string command) {
return new PurchaseLaRucheDto() {
datePurchase = date,
command = command
};
}
#endregion
public static string EncryptPassword(string password, byte[] salt)
{
string encryptedPassw = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8
));
return encryptedPassw;
}
public static JwtSecurityToken GetToken(string idUser, string secret, string validIssuer, string validAudience)
{
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, idUser),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
authClaims.Add(new Claim(ClaimTypes.Role, "Admin"));
authClaims.Add(new Claim(ClaimTypes.Role, "Classic"));
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var token = new JwtSecurityToken(
issuer: validIssuer,
audience: validAudience,
expires: DateTime.Now.AddDays(5),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return token;
}
}
}

View File

@ -0,0 +1,101 @@
using System.Linq.Expressions;
using System.Collections;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
#nullable disable
namespace GiecChallenge.Tests
{
public static class ICollectionExtensions
{
public static IQueryable<T> AsAsyncQueryable<T>(this ICollection<T> source) =>
new AsyncQueryable<T>(source.AsQueryable());
}
internal class AsyncQueryable<T> : IAsyncEnumerable<T>, IQueryable<T>
{
private IQueryable<T> Source;
public AsyncQueryable(IQueryable<T> source)
{
Source = source;
}
public Type ElementType => typeof(T);
public Expression Expression => Source.Expression;
public IQueryProvider Provider => new AsyncQueryProvider<T>(Source.Provider);
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new AsyncEnumeratorWrapper<T>(Source.GetEnumerator());
}
public IEnumerator<T> GetEnumerator() => Source.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
internal class AsyncQueryProvider<T> : IQueryProvider, IAsyncQueryProvider
{
private readonly IQueryProvider Source;
public AsyncQueryProvider(IQueryProvider source)
{
Source = source;
}
public IQueryable CreateQuery(Expression expression) =>
Source.CreateQuery(expression);
public IQueryable<TElement> CreateQuery<TElement>(Expression expression) =>
new AsyncQueryable<TElement>(Source.CreateQuery<TElement>(expression));
public object Execute(Expression expression) => Execute<T>(expression);
public TResult Execute<TResult>(Expression expression) =>
Source.Execute<TResult>(expression);
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
var expectedResultType = typeof(TResult).GetGenericArguments()[0];
var executionResult = typeof(IQueryProvider)
.GetMethod(
name: nameof(IQueryProvider.Execute),
genericParameterCount: 1,
types: new[] {typeof(Expression)})
.MakeGenericMethod(expectedResultType)
.Invoke(this, new[] {expression});
return (TResult) typeof(Task).GetMethod(nameof(Task.FromResult))
?.MakeGenericMethod(expectedResultType)
.Invoke(null, new[] {executionResult});
}
TResult IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) =>
ExecuteAsync<TResult>(expression, cancellationToken);
}
internal class AsyncEnumeratorWrapper<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> Source;
public AsyncEnumeratorWrapper(IEnumerator<T> source)
{
Source = source;
}
public T Current => Source.Current;
public ValueTask DisposeAsync()
{
return new ValueTask(Task.CompletedTask);
}
public ValueTask<bool> MoveNextAsync()
{
return new ValueTask<bool>(Source.MoveNext());
}
}
}

View File

@ -0,0 +1,148 @@
using Moq;
using GiecChallenge.Controllers;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
namespace GiecChallenge.Tests
{
public class AlimentControllerTests
{
private Mock<ILogger<AlimentController>> _logger = null!;
private Mock<IAlimentRepository> _alimentRepository = null!;
private AlimentController _controller = null!;
private List<AlimentDto> _allAliments = null!;
[SetUp]
public void Setup()
{
_logger = new Mock<ILogger<AlimentController>>();
_alimentRepository = new Mock<IAlimentRepository>();
_controller = new AlimentController(_logger.Object, _alimentRepository.Object);
_allAliments = Common.GetAlimentDto();
}
[Test]
public async Task GetAllAliments()
{
_alimentRepository.Setup(p => p.GetAllAliments()).ReturnsAsync(_allAliments);
var result = await _controller.Get() as OkObjectResult;
Assert.AreEqual(result!.Value, _allAliments);
}
[Test]
[TestCase("tom")]
[TestCase("tomate")]
public async Task GetByCode(string name)
{
_alimentRepository.Setup(p => p.GetAliments(It.IsAny<string>())).ReturnsAsync(new List<AlimentDto>() { _allAliments.First() });
var result = await _controller.GetByName(name) as OkObjectResult;
Assert.AreEqual(result!.Value, new List<AlimentDto>() { _allAliments.First() });
}
[Test]
[TestCase("pou")]
[TestCase("tos")]
public async Task GetByCodeNoAnswer(string name)
{
_alimentRepository.Setup(p => p.GetAliments(It.IsAny<string>())).ReturnsAsync(new List<AlimentDto>());
var result = await _controller.GetByName(name) as OkObjectResult;
Assert.AreEqual(result!.Value, new List<AlimentDto>());
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task GetById(string id)
{
_alimentRepository.Setup(p => p.GetAliment(It.IsAny<string>())).ReturnsAsync(_allAliments.First());
var result = await _controller.GetByCode(id) as OkObjectResult;
Assert.AreEqual(result!.Value, _allAliments.First());
}
[Test]
[TestCase("5")]
[TestCase("6")]
public async Task GetByIdNoAnswerAsync(string ciqual)
{
var expected = new AlimentDto();
_alimentRepository.Setup(p => p.GetAliment(It.IsAny<string>())).ThrowsAsync(new Exception(string.Concat(ciqual, " does not exist")));
var ex = await _controller.GetByCode(ciqual) as ObjectResult;
Assert.AreEqual(ex!.StatusCode, 500);
}
[Test]
[TestCase("Poire", "1005")]
[TestCase("Abricot", "1006")]
public async Task Post(string name, string ciqual)
{
bool postIsOk = true;
var alimentToSend = Common.GetAlimentDtoTest(name, ciqual);
_alimentRepository.Setup(p => p.Create(alimentToSend!));
try {
await _controller.Post(alimentToSend);
}
catch {
postIsOk = false;
}
Assert.AreEqual(postIsOk, true);
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task PostCiqualAlreadyExistAsync(string ciqual)
{
var alimentToSend = _allAliments.First(a => a.ciqual_code == ciqual);
_alimentRepository.Setup(p =>p.Create(alimentToSend!)).ThrowsAsync(new Exception(string.Concat(ciqual, " already exists")));
var ex = await _controller.Post(alimentToSend) as ObjectResult;
Assert.AreEqual(ex!.StatusCode, 500);
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task Update(string ciqual)
{
bool postIsOk = true;
var alimentToSend = _allAliments.First(a => a.ciqual_code == ciqual);
alimentToSend.nom_francais = "toto";
_alimentRepository.Setup(p => p.Update(alimentToSend!));
try {
await _controller.Update(alimentToSend);
}
catch {
postIsOk = false;
}
Assert.AreEqual(postIsOk, true);
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task UpdateNotExistAsync(string ciqual)
{
var alimentToSend = _allAliments.First(a => a.ciqual_code == ciqual);
alimentToSend.nom_francais = "toto";
_alimentRepository.Setup(p =>p.Update(alimentToSend!)).ThrowsAsync(new Exception("Aliment does not exist"));
var ex = await _controller.Update(alimentToSend) as ObjectResult;
Assert.AreEqual(ex!.StatusCode, 500);
}
}
}

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="moq" Version="4.18.2" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GiecChallenge\GiecChallenge.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,139 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class AlimentServiceTest
{
private Mock<ILogger<AlimentService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private AlimentService _service = null!;
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AlimentProfile());
cfg.AddProfile(new ProductProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<AlimentService>>();
_context = Common.GetContext();
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_context.Setup(g => g.ProductUserTranslations).Returns(Common.GetMockDbSet<ProductUserTranslation>(Common.GetProductUserTranslations()).Object);
_context.Setup(g => g.ProductSubGroups).Returns(Common.GetMockDbSet<ProductSubGroup>(Common.GetProductSubGroup()).Object);
_context.Setup(g => g.Aliments).Returns(Common.GetMockDbSet<Aliment>(Common.GetAliments()).Object);
_service = new AlimentService(_logger.Object, mapper, _context.Object);
}
[Test]
public async Task GetAllAliments()
{
var result = await _service.GetAllAliments();
Assert.AreEqual(result.Count, Common.GetAliments().Count);
}
[Test]
[TestCase("tom", "1002")]
[TestCase("tomate", "1002")]
[TestCase("poire", "1004")]
public async Task GetByName(string name, string ciqual)
{
var result = await _service.GetAliments(name);
Assert.AreEqual(result.Any(re => re.ciqual_code == ciqual), true);
}
[Test]
[TestCase("pomme")]
[TestCase("coca")]
public async Task GetByNameNothing(string name)
{
var result = await _service.GetAliments(name);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task GetAliment(string id)
{
var result = await _service.GetAliment(id);
Assert.AreEqual(Common.GetAliments().First(al => al.ciqual == id).ciqual, id);
}
[Test]
[TestCase("10000002")]
[TestCase("10000003")]
public void GetAlimentNothing(string id)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetAliment(id));
Assert.That(ex!.Message, Is.EqualTo(string.Concat(id, " does not exist")));
}
[Test]
[TestCase("10000002")]
[TestCase("10000003")]
public async Task Create(string id)
{
var aliment = Common.GetAlimentTest("poire", id);
var alimentDto = Common.GetAlimentDtoTest("poire", id);
await _service.Create(alimentDto);
Assert.AreEqual(_context.Object.Aliments.Any(l => l.ciqual == id), true);
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public void CreateAlreadyExists(string id)
{
var aliment = Common.GetAlimentTest("poire", id);
var alimentDto = Common.GetAlimentDtoTest("poire", id);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(alimentDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat(id, " already exists")));
}
[Test]
[TestCase("1002")]
[TestCase("1003")]
public async Task Update(string id)
{
bool postIsOk = true;
var alimentDto = Common.GetAlimentDtoTest("poire", id);
try {
await _service.Update(alimentDto);
}
catch {
postIsOk = false;
}
Assert.AreEqual(postIsOk, true);
}
[Test]
[TestCase("10000002")]
[TestCase("10000003")]
public void UpdateDoesNotExists(string id)
{
var alimentDto = Common.GetAlimentDtoTest("poire", id);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(alimentDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Aliment does not exist")));
}
}
}

View File

@ -0,0 +1,132 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class LanguageServiceTest
{
private Mock<ILogger<LanguageService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private LanguageService _service = null!;
private List<LanguageDto> _allLanguagesDTO = null!;
private string _language = "FR";
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new LanguageProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<LanguageService>>();
_allLanguagesDTO = Common.GetLanguagesDto("Français", "English");
_context = Common.GetContext();
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_context.Setup(g => g.LanguageLanguages).Returns(Common.GetMockDbSet<LanguageLanguage>(Common.GetLanguages().SelectMany(l => l.names).ToList()).Object);
_service = new LanguageService(_logger.Object, mapper, _context.Object);
}
[Test]
public async Task GetAllLanguages()
{
var result = await _service.GetAllLanguages();
Assert.AreEqual(result.Count, Common.GetLanguages().Count);
}
[Test]
[TestCase("Anglais")]
[TestCase("çais")]
public async Task GetByName(string name)
{
var result = await _service.GetLanguages(name, _language);
Assert.AreEqual(result.Any(re => re.names.Any(rer => rer.name.ToLower().Contains(name.ToLower()))), true);
}
[Test]
[TestCase("pomme")]
[TestCase("poire")]
public async Task GetByNameNothing(string name)
{
var result = await _service.GetLanguages(name, _language);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public async Task GetLanguage(Guid id)
{
var result = await _service.GetLanguage(id);
Assert.AreEqual(result!.id, id);
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33")]
public void GetLanguageNothing(Guid id)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetLanguage(id));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language does not exist")));
}
[Test]
[TestCase("IT", "Italien", "IT")]
[TestCase("ES", "Espagnol", "FR")]
public async Task Create(string isoCode, string name, string languageOfName)
{
var languageDto = Common.GetLanguageDtoTest(isoCode, name, languageOfName);
await _service.Create(languageDto);
Assert.AreEqual(_context.Object.Languages.Any(l => l.ISOCode == isoCode), true);
Assert.AreEqual(_context.Object.Languages.Any(l => l.ISOCode == isoCode && l.names.Any()), true);
}
[Test]
[TestCase("FR", "Français", "FR")]
[TestCase("EN", "English", "EN")]
public void CreateAlreadyExists(string isoCode, string name, string languageOfName)
{
var languageDto = Common.GetLanguageDtoTest(isoCode, name, languageOfName);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(languageDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language already exists")));
}
[Test]
[TestCase("f3390acd-acf2-4ab9-8d39-25b216182320", "FR", "Italien", "FR")]
[TestCase("0b1307be-9ffd-4dcd-9431-4fe58b6420f7", "ES", "Espagnol", "FR")]
[TestCase("d7ee9249-1edc-4158-ad4d-9892fb703e47", "EN", "German", "EN")]
public async Task Update(Guid id, string isoCode, string name, string languageOfName)
{
var languageDto = Common.GetLanguageDtoTest(isoCode, name, languageOfName);
await _service.Update(id, languageDto);
Assert.True(_context.Object.Languages.Any(l => l.names.Any(ln => ln.language.ISOCode == languageOfName)));
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e", "FR", "Français")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33", "EN", "English")]
public void UpdateDoesNotExists(Guid id, string isoCode, string name)
{
var languageDto = Common.GetLanguageDtoTest(isoCode, name);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, languageDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language does not exist")));
}
}
}

View File

@ -0,0 +1,130 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class ProductGroupServiceTest
{
private Mock<ILogger<GroupService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private GroupService _service = null!;
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new GroupProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<GroupService>>();
_context = Common.GetContext();
_context.Setup(g => g.ProductGroups).Returns(Common.GetMockDbSet<ProductGroup>(Common.GetGroups()).Object);
_context.Setup(g => g.ProductGroupLanguages).Returns(Common.GetMockDbSet<ProductGroupLanguage>(Common.GetGroupLanguage()).Object);
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_context.Setup(g => g.LanguageLanguages).Returns(Common.GetMockDbSet<LanguageLanguage>(Common.GetLanguages().SelectMany(l => l.names).ToList()).Object);
_service = new GroupService(_logger.Object, mapper, _context.Object);
}
[Test]
public async Task GetAllGroups()
{
var result = await _service.GetAllGroups();
Assert.AreEqual(result.Count, Common.GetGroups().Count);
}
[Test]
[TestCase("aliMent", "FR")]
[TestCase("tro", "EN")]
public async Task GetByName(string name, string language)
{
var result = await _service.GetGroups(name, language);
Assert.AreEqual(result.Any(re => re.names.Any(rer => rer.name.ToLower().Contains(name.ToLower()))), true);
}
[Test]
[TestCase("pomme", "FR")]
[TestCase("poire", "EN")]
[TestCase("aliMent", "EN")]
public async Task GetByNameNothing(string name, string language)
{
var result = await _service.GetGroups(name, language);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("b21a6403-f428-454f-942d-dbd1fc3fa551")]
[TestCase("8f46bf6f-6cbf-47ac-8d51-039eabc820c3")]
public async Task GetGroup(Guid id)
{
var result = await _service.GetGroup(id);
Assert.AreEqual(result!.id, id);
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33")]
public void GetGroupNothing(Guid id)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetGroup(id));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group does not exist")));
}
[Test]
[TestCase("Transport", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("Commute", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public async Task Create(string name, string language)
{
var groupDto = Common.GetGroupDtoTest(name, language);
await _service.Create(groupDto);
Assert.AreEqual(_context.Object.ProductGroups.Any(l => l.names.Any(ln => ln.name == name)), true);
}
[Test]
[TestCase("aliMent", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("ElectroniC device", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public void CreateAlreadyExists(string name, string language)
{
var groupDto = Common.GetGroupDtoTest(name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(groupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group already exists")));
}
[Test]
[TestCase("b21a6403-f428-454f-942d-dbd1fc3fa551", "Nourriture", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("8f46bf6f-6cbf-47ac-8d51-039eabc820c3", "Materiel electronique", "f3390acd-acf2-4ab9-8d39-25b216182320")]
public async Task Update(Guid id, string name, string isoCode)
{
var groupDto = Common.GetGroupDtoTest(name, isoCode);
await _service.Update(id, groupDto);
Assert.True(_context.Object.ProductGroups.Any(l => l.names.Any(ln => ln.name == name)));
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e", "f3390acd-acf2-4ab9-8d39-25b216182320", "Français")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7", "English")]
public void UpdateDoesNotExists(Guid id, string isoCode, string name)
{
var groupDto = Common.GetGroupDtoTest(isoCode, name);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, groupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group does not exist")));
}
}
}

View File

@ -0,0 +1,334 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class ProductServiceTest
{
private Mock<ILogger<ProductService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private ProductService _service = null!;
private List<ProductDto> _allProductsDTO = null!;
private string _language = "f3390acd-acf2-4ab9-8d39-25b216182320";
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new ProductProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<ProductService>>();
_allProductsDTO = Common.GetProductsDto();
_context = Common.GetContext();
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_context.Setup(g => g.ProductSubGroups).Returns(Common.GetMockDbSet<ProductSubGroup>(Common.GetProductSubGroup()).Object);
_context.Setup(g => g.ProductGroups).Returns(Common.GetMockDbSet<ProductGroup>(Common.GetProductGroup()).Object);
_context.Setup(g => g.ProductUserTranslations).Returns(Common.GetMockDbSet<ProductUserTranslation>(Common.GetProductUserTranslations()).Object);
_context.Setup(g => g.Products).Returns(Common.GetMockDbSet<Product>(Common.GetProducts()).Object);
_context.Setup(g => g.Users).Returns(Common.GetMockDbSet<User>(Common.GetUsers()).Object);
_service = new ProductService(_logger.Object, mapper, _context.Object);
}
[Test]
public async Task GetAllProducts()
{
var result = await _service.GetAllProducts();
Assert.AreEqual(result.Count, Common.GetProducts().Count);
}
[Test]
[TestCase("ip")]
[TestCase("pen", "EN")]
public async Task GetByName(string name, string language = "FR")
{
var result = await _service.GetProducts(name, language);
Assert.AreEqual(result.Any(re => re.names.Any(rer => rer.name.ToLower().Contains(name))), true);
}
[Test]
[TestCase("pomme")]
[TestCase("poire")]
public async Task GetByNameNothing(string name)
{
var result = await _service.GetProducts(name, _language);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("e5f89b1d-171f-4460-a2cc-18e1534b5bae")]
[TestCase("526ea756-50da-486f-8a44-5e964f249c1e")]
public async Task GetProduct(Guid id)
{
var result = await _service.GetProduct(id);
Assert.AreEqual(result!.id, id);
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33")]
public void GetProductNothing(Guid id)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetProduct(id));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product does not exist")));
}
[Test]
[TestCase("991979cd-b95f-4e9a-85e7-e1f7ce6932fb", "526ea756-50da-486f-8a44-5e964f249c1e")]
[TestCase("3a69d206-7236-11ed-a1eb-0242ac120002", "e5f89b1d-171f-4460-a2cc-18e1534b5bae")]
public async Task GetProductByGroup(string group, Guid id)
{
var result = await _service.GetProductsByGroup(group);
Assert.AreEqual(result!.First().id, id);
}
[Test]
[TestCase("Voiture")]
[TestCase("Animal")]
public void GetProductByGroupBadValue(string group)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetProductsByGroup(group));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group ", group, " doesn't exist")));
}
[Test]
[TestCase("fd837d14-a085-11ed-a8fc-0242ac120002")]
[TestCase("fd837ea4-a085-11ed-a8fc-0242ac120002")]
public async Task GetProductByGroupNothing(string group)
{
var result = await _service.GetProductsByGroup(group);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("04f3eb50-6119-487a-86a6-b6c24e620536", "e5f89b1d-171f-4460-a2cc-18e1534b5bae")]
[TestCase("4f52f771-7752-472f-921e-88824fc4c5d5", "526ea756-50da-486f-8a44-5e964f249c1e")]
public async Task GetProductBySubGroup(string subgroup, Guid id)
{
var result = await _service.GetProductsBySubGroup(subgroup);
Assert.AreEqual(result!.First().id, id);
}
[Test]
[TestCase("Voiture")]
[TestCase("Animal")]
public void GetProductBySubGroupBadValue(string subgroup)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetProductsBySubGroup(subgroup));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Sub group ", subgroup, " doesn't exist")));
}
[Test]
[TestCase("db815ede-1764-46c4-9f37-7a80851930a2")]
[TestCase("fd83786e-a085-11ed-a8fc-0242ac120002")]
public async Task GetProductBySubGroupNothing(string subgroup)
{
var result = await _service.GetProductsBySubGroup(subgroup);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("iPhone", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
[TestCase("Apple Watch", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public async Task Create(string name, string language)
{
var productDto = Common.GetProductDtoTest(name, Common.GetProductSubGroup().First().id.ToString(), language);
await _service.Create(productDto);
Assert.AreEqual(_context.Object.Products.Any(l => l.names.Any(ln => ln.name == name)), true);
}
[Test]
[TestCase("iPhone", "0b1307be-9ffd-4dcd-9431-4fe58b6420d7")]
[TestCase("Apple Watch", "0b1307be-9ffd-4dcd-9431-4fe58b6420g7")]
public void CreateLanguageBadValue(string name, string language)
{
var productDto = Common.GetProductDtoTest(name, Common.GetProductSubGroup().First().id.ToString(), language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language ", language, " doesn't exist")));
}
[Test]
[TestCase("iPhone", "0b1307be-9ffd-4dcd-9431-4fe58b6420d7")]
[TestCase("Apple Watch", "0b1307be-9ffd-4dcd-9431-4fe58b6420g7")]
public void CreateLanguageNotExists(string name, string language)
{
var productDto = Common.GetProductDtoTest(name, Common.GetProductSubGroup().First().id.ToString(), language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language ", language, " doesn't exist")));
}
[Test]
[TestCase("iPhone", "Tablet", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
[TestCase("Apple Watch", "Watch", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public void CreateGroupNotExists(string name, string group, string language)
{
var productDto = Common.GetProductDtoTest(name, group, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group does not exist")));
}
[Test]
[TestCase("iPad", "04f3eb50-6119-487a-86a6-b6c24e620536", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
[TestCase("chou vert", "4f52f771-7752-472f-921e-88824fc4c5d5", "f3390acd-acf2-4ab9-8d39-25b216182320")]
public void CreateAlreadyExists(string name, string group, string language)
{
var productDto = Common.GetProductDtoTest(name, group, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product already exists")));
}
[Test]
[TestCase("e5f89b1d-171f-4460-a2cc-18e1534b5bae", "iPhone", "04f3eb50-6119-487a-86a6-b6c24e620536", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
[TestCase("526ea756-50da-486f-8a44-5e964f249c1e", "Poire", "4f52f771-7752-472f-921e-88824fc4c5d5", "f3390acd-acf2-4ab9-8d39-25b216182320")]
public async Task Update(Guid id, string name, string group, string language)
{
bool postIsOk = true;
var productDto = Common.GetProductDtoTest(name, group, language);
try {
await _service.Update(id, productDto);
}
catch {
postIsOk = false;
}
Assert.AreEqual(postIsOk, true);
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33")]
public void UpdateDoesNotExists(Guid id)
{
var productDto = Common.GetProductDtoTest("poire", "4f52f771-7752-472f-921e-88824fc4c5d5", "f3390acd-acf2-4ab9-8d39-25b216182320");
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product does not exist")));
}
[Test]
[TestCase("e5f89b1d-171f-4460-a2cc-18e1534b5bae", "iPhone", "04f3eb50-6119-487a-86a6-b6c24e620536", "CN")]
[TestCase("526ea756-50da-486f-8a44-5e964f249c1e", "Poire", "4f52f771-7752-472f-921e-88824fc4c5d5", "FI")]
public void UpdateLanguageNotExists(Guid id, string name, string group, string language)
{
var productDto = Common.GetProductDtoTest(name, group, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language ", language, " doesn't exist")));
}
[Test]
[TestCase("e5f89b1d-171f-4460-a2cc-18e1534b5bae", "iPhone", "Phone", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
[TestCase("526ea756-50da-486f-8a44-5e964f249c1e", "Poire", "Alcool", "f3390acd-acf2-4ab9-8d39-25b216182320")]
public void UpdateGroupNotExists(Guid id, string name, string group, string language)
{
var productDto = Common.GetProductDtoTest(name, group, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, productDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group does not exist")));
}
[Test]
[TestCase("Galaxy Tab", "0a891394-be17-473b-9924-eccaf6ce79ed", "e5f89b1d-171f-4460-a2cc-18e1534b5bae")]
[TestCase("Waterman", "0a891394-be17-473b-9924-eccaf6ce79ed", "526ea756-50da-486f-8a44-5e964f249c1e")]
public async Task CreateUserTranslation(string name, string user, string product)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, user, product, string.Empty);
await _service.CreateTranslation(productUserTranslationDTO);
Assert.True(_context.Object.ProductUserTranslations.Any(l => l.name == name && l.user.id.ToString() == user && l.product.id.ToString() == product));
}
[Test]
[TestCase("Galaxy Tab", "0a891394-be17-473b-9924-eccafwce79ed", "e5f89b1d-171f-4460-a2cc-18e1534b5bae")]
[TestCase("Waterman", "0a891394-be17-473b-9924-eccaf6ci79ed", "526ea756-50da-486f-8a44-5e964f249c1e")]
public void CreateUserTranslationUserNotExist(string name, string user, string product)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, user, product, string.Empty);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.CreateTranslation(productUserTranslationDTO));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("User does not exist")));
}
[Test]
[TestCase("Galaxy Tab", "0a891394-be17-473b-9924-eccaf6ce79ed", "e5f89b1d-171f-4460-a2cd-18e1534b5bae")]
[TestCase("Waterman", "0a891394-be17-473b-9924-eccaf6ce79ed", "526ea756-50da-486f-8a4y-5e964f249c1e")]
public void CreateUserTranslationProductNotExists(string name, string user, string product)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, user, product, string.Empty);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.CreateTranslation(productUserTranslationDTO));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product does not exist")));
}
[Test]
[TestCase("tomate", "0a891394-be17-473b-9924-eccaf6ce79ed", "479d91d4-8f93-433f-8b4c-b5b08c12db5c")]
[TestCase("chou", "9beb47ab-0def-437c-b510-02d8f9623ebb", "5823ec98-2726-4b39-b01e-8453bbde5524")]
public async Task UpdateUserTranslation(string name, string user, string id)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, string.Empty, string.Empty, id);
var previousName = _context.Object.ProductUserTranslations.First(l => l.id == Guid.Parse(id)).name;
await _service.UpdateTranslation(productUserTranslationDTO, Guid.Parse(user));
Assert.AreNotEqual(_context.Object.ProductUserTranslations.First(l => l.id == Guid.Parse(id)).name, previousName);
}
[Test]
[TestCase("tomate", "0a891394-be17-473b-9924-eccaf6ce79ed", "f917a5bf-4a96-496b-90cc-ad24d6d4f4fe")]
[TestCase("chou", "9beb47ab-0def-437c-b510-02d8f9623ebb", "debc6de1-48ce-430c-b4e4-0ab5024272f4")]
public void UpdateUserTranslationNotExists(string name, string user, string id)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, string.Empty, string.Empty, id);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.UpdateTranslation(productUserTranslationDTO, Guid.Parse(user)));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Translation doesn't exist")));
}
[Test]
[TestCase("tomate", "0a891394-be17-473b-9924-eccaf6ce79ed", "479d91d4-8f93-433f-8b4c-b5b08c12db5c")]
[TestCase("chou", "9beb47ab-0def-437c-b510-02d8f9623ebb", "5823ec98-2726-4b39-b01e-8453bbde5524")]
public async Task DeleteUserTranslation(string name, string user, string id)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, string.Empty, string.Empty, id);
await _service.DeleteTranslation(productUserTranslationDTO, Guid.Parse(user));
Assert.IsTrue(_context.Object.ProductUserTranslations.Any(l => l.id == Guid.Parse(id)));
}
[Test]
[TestCase("tomate", "0a891394-be17-473b-9924-eccaf6ce79ed", "f917a5bf-4a96-496b-90cc-ad24d6d4f4fe")]
[TestCase("chou", "9beb47ab-0def-437c-b510-02d8f9623ebb", "debc6de1-48ce-430c-b4e4-0ab5024272f4")]
public void DeleteUserTranslationNotExists(string name, string user, string id)
{
var productUserTranslationDTO = Common.GetProductTranslationDtoTest(name, string.Empty, string.Empty, id);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.DeleteTranslation(productUserTranslationDTO, Guid.Parse(user)));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Translation does not exist")));
}
}
}

View File

@ -0,0 +1,176 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class ProductSubGroupServiceTest
{
private Mock<ILogger<SubGroupService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private SubGroupService _service = null!;
private List<GroupDto> _allGroupsDTO = null!;
private string _Group = "FR";
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new SubGroupProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<SubGroupService>>();
_allGroupsDTO = Common.GetGroupsDto("Français", "English");
_context = Common.GetContext();
_context.Setup(g => g.ProductGroups).Returns(Common.GetMockDbSet<ProductGroup>(Common.GetGroups()).Object);
_context.Setup(g => g.ProductSubGroups).Returns(Common.GetMockDbSet<ProductSubGroup>(Common.GetSubGroups()).Object);
_context.Setup(g => g.ProductSubGroupLanguages).Returns(Common.GetMockDbSet<ProductSubGroupLanguage>(Common.GetSubGroupLanguage()).Object);
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_service = new SubGroupService(_logger.Object, mapper, _context.Object);
}
[Test]
public async Task GetAllGroups()
{
var result = await _service.GetAllSubGroups();
Assert.AreEqual(result.Count, Common.GetGroups().Count);
}
[Test]
[TestCase("Boisson")]
[TestCase("hon")]
public async Task GetByName(string name)
{
var result = await _service.GetSubGroups(name, _Group);
Assert.AreEqual(result.Any(re => re.names.Any(rer => rer.name.ToLower().Contains(name.ToLower()))), true);
}
[Test]
[TestCase("vian")]
[TestCase("poire")]
public async Task GetByNameNothing(string name)
{
var result = await _service.GetSubGroups(name, _Group);
Assert.AreEqual(result.Any(), false);
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57")]
public async Task GetSubGroup(Guid id)
{
var result = await _service.GetSubGroup(id);
Assert.AreEqual(result!.id, id);
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33")]
public void GetSubGroupNothing(Guid id)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetSubGroup(id));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Sub Group does not exist")));
}
[Test]
[TestCase("Viande", "b21a6403-f428-454f-942d-dbd1fc3fa551", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("Tablet", "8f46bf6f-6cbf-47ac-8d51-039eabc820c3", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public async Task Create(string name, string groupOfName, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(name, groupOfName, language);
await _service.Create(subGroupDto);
Assert.AreEqual(_context.Object.ProductSubGroups.Any(l => l.names.Any(ln => ln.name == name)), true);
}
[Test]
[TestCase("Boisson", "b21a6403-f428-454f-942d-dbd1fc3fa551", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("Smartphone", "8f46bf6f-6cbf-47ac-8d51-039eabc820c3", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public void CreateAlreadyExists(string name, string groupOfName, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(name, groupOfName, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Sub Group already exists")));
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "Tablet", "8f46bf6f-6cbf-47ac-8d51-039eabc820c3", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57", "Viande", "b21a6403-f428-454f-942d-dbd1fc3fa551", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public async Task Update(Guid id, string name, string groupOfName, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(name, groupOfName, language);
await _service.Update(id, subGroupDto);
Assert.True(_context.Object.ProductSubGroups.Any(l => l.names.Any(ln => ln.name == name)));
}
[Test]
[TestCase("46c619b1-1859-4665-bc8b-cf51eb30777e", "Tablet", "991979cd-b95f-4e9a-85e7-e1f7ce6932fb", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("eca28033-9954-498f-89d4-a911e40f5a33", "Viande", "3a69d206-7236-11ed-a1eb-0242ac120002", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public void UpdateDoesNotExists(Guid id, string isoCode, string name, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(isoCode, name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Sub Group does not exist")));
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "Tablet", "Elec", "FR")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57", "Viande", "Bouffe", "EN")]
public void UpdateWithGroupBadFormat(Guid id, string isoCode, string name, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(isoCode, name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat(name, " is not valid")));
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "Tablet", "bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "f3390acd-acf2-4ab9-8d39-25b216182320")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57", "Viande", "1dda078c-d158-4078-aa8e-981d5ac5cd57", "0b1307be-9ffd-4dcd-9431-4fe58b6420f7")]
public void UpdateWithGroupUnknown(Guid id, string isoCode, string name, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(isoCode, name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Group does not exist")));
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "Tablet", "991979cd-b95f-4e9a-85e7-e1f7ce6932fb", "IT")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57", "Viande", "3a69d206-7236-11ed-a1eb-0242ac120002", "ES")]
public void UpdateWithLanguageBadValue(Guid id, string isoCode, string name, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(isoCode, name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat(language, " is not valid")));
}
[Test]
[TestCase("bf0cc5d3-2b4f-4761-ac4f-5dc25005aa32", "Tablet", "991979cd-b95f-4e9a-85e7-e1f7ce6932fb", "991979cd-b95f-4e9a-85e7-e1f7ce6932fb")]
[TestCase("1dda078c-d158-4078-aa8e-981d5ac5cd57", "Viande", "3a69d206-7236-11ed-a1eb-0242ac120002", "3a69d206-7236-11ed-a1eb-0242ac120001")]
public void UpdateWithLanguageUnknown(Guid id, string isoCode, string name, string language)
{
var subGroupDto = Common.GetSubGroupDtoTest(isoCode, name, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(id, subGroupDto));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language ", language, " doesn't exist")));
}
}
}

View File

@ -0,0 +1,384 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
namespace GiecChallenge.Tests
{
public class PurchaseServiceTest
{
private Mock<ILogger<PurchaseService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private PurchaseService _service = null!;
private List<UserDto> _allUsersDTO = null!;
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new PurchaseProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<PurchaseService>>();
_context = Common.GetContext();
_context.Setup(x => x.SetEntityStateModified(It.IsAny<Purchase>()));
_context.Setup(g => g.Purchases).Returns(Common.GetMockDbSet<Purchase>(Common.GetPurchases()).Object);
_context.Setup(g => g.Products).Returns(Common.GetMockDbSet<Product>(Common.GetProducts()).Object);
_context.Setup(g => g.ProductPurchases).Returns(Common.GetMockDbSet<ProductPurchase>(Common.GetProductPurchases()).Object);
_context.Setup(g => g.ProductUserTranslations).Returns(Common.GetMockDbSet<ProductUserTranslation>(Common.GetProductUserTranslations()).Object);
_context.Setup(g => g.Users).Returns(Common.GetMockDbSet<User>(Common.GetUsers()).Object);
_context.Setup(g => g.Currencies).Returns(Common.GetMockDbSet<Currency>(Common.GetCurrencies()).Object);
_context.Setup(g => g.CarbonLoans).Returns(Common.GetMockDbSet<CarbonLoan>(Common.GetCarbonLoans()).Object);
_service = new PurchaseService(_logger.Object, mapper, _context.Object);
}
[Test]
[TestCase("0a891394-be17-473b-9924-eccaf6ce79ed")]
[TestCase("9beb47ab-0def-437c-b510-02d8f9623ebb")]
public async Task GetAll(string idUser)
{
var result = await _service.GetAll(Guid.Parse(idUser));
Assert.AreEqual(_context.Object.Purchases.Count(u => u.user.id == Guid.Parse(idUser)), result.Count());
}
[Test]
[TestCase("9a3f9eb6-1f46-46b5-aa66-b0e3d0b37c82")]
[TestCase("d89b6c34-ae14-43f6-b5e0-26f6265a9bd2")]
public void GetAllUserNotCorrect(string idUser)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetAll(Guid.Parse(idUser)));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Nice try")));
}
[Test]
[TestCase("0a891394-be17-473b-9924-eccaf6ce79ed", "30/11/2021", "05/01/2022", 2)]
[TestCase("0a891394-be17-473b-9924-eccaf6ce79ed", "30/11/2021", "02/01/2022", 1)]
[TestCase("9beb47ab-0def-437c-b510-02d8f9623ebb", "30/11/2021", "05/01/2022", 1)]
[TestCase("9beb47ab-0def-437c-b510-02d8f9623ebb", "05/11/2022", "06/11/2022", 0)]
public async Task GetByDate(string idUser, string dateBegin, string dateEnd, int expectedResult)
{
var result = await _service.GetBetweenDate(Guid.Parse(idUser), DateTime.Parse(dateBegin), DateTime.Parse(dateEnd));
Assert.AreEqual(expectedResult, result.Count());
}
[Test]
[TestCase("9a3f9eb6-1f46-46b5-aa66-b0e3d0b37c82", "30/11/2021", "05/01/2022", 2)]
[TestCase("d89b6c34-ae14-43f6-b5e0-26f6265a9bd2", "30/11/2021", "05/01/2022", 1)]
public void GetUserNotCorrect(string idUser, string dateBegin, string dateEnd, int expectedResult)
{
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.GetBetweenDate(Guid.Parse(idUser), DateTime.Parse(dateBegin), DateTime.Parse(dateEnd)));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Nice try")));
}
[Test]
[TestCase("05/11/2023",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.0, 12.2},
new[] {1.2, 2.3})]
[TestCase("07/12/2023",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.0, 12.2},
new[] {3, 4.3})]
public async Task Create(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
await _service.Create(Guid.Parse(idUser), purchaseToTest);
var purchase = _context.Object.Purchases.First(u => u.datePurchase == date);
foreach (string product in products) {
Assert.IsTrue(purchase.products.Any(p => p.product.id == Guid.Parse(product)));
}
}
[Test]
[TestCase("01/01/2023",
"9a3f9eb6-1f46-46b5-aa66-b0e3d0b37c82",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"d89b6c34-ae14-43f6-b5e0-26f6265a9bd2",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.0},
new[] {1.2, 2.3})]
public void CreateUserNotExists(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Nice try")));
}
[Test]
[TestCase("01/01/2023",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "5a39736d-de7b-4b26-b4c6-b5841a52ddbf"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"4ec6db81-f8e0-4343-9973-f6a91e4d4c29", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
public void CreateProductNotExists(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product does not exist")));
}
[Test]
[TestCase("01/01/2023",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"f150f3ca-1a18-40e1-a01a-fad22724514a", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "f2672cf5-761e-4f5a-8fc2-b3264fc5dd0d"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
public void CreateCurrencyNotExists(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Currency does not exist")));
}
[Test]
[TestCase("01/01/2023",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {-5, 1.22},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {1.25, -1},
new[] {1.2, 2.3})]
public void CreatePriceNotCorrect(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Price must be superior than 0")));
}
[Test]
[TestCase("01/01/2023",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {-5, 1.22},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {1.25, -1},
new[] {1.2, 2.3})]
public void CreateNoProduct(DateTime date, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Create(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("No product selected")));
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.0, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.0, 12.2},
new[] {3, 4.51})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.0, 12.2},
new[] {5.6, 6.7})]
public async Task Update(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
await _service.Update(Guid.Parse(idUser), purchaseToTest);
var purchase = _context.Object.Purchases.First(p => p.id == Guid.Parse(idPurchase));
foreach (string product in products) {
Assert.IsTrue(purchase.products.Any(p => p.product.id == Guid.Parse(product)));
}
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"9a3f9eb6-1f46-46b5-aa66-b0e3d0b37c82",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"d89b6c34-ae14-43f6-b5e0-26f6265a9bd2",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.0},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {-5, 1.22},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {1.25, -1},
new[] {1.2, 2.3})]
public void UpdateUserNotExists(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Purchase does not exist")));
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "5a39736d-de7b-4b26-b4c6-b5841a52ddbf"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"4ec6db81-f8e0-4343-9973-f6a91e4d4c29", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
public void UpdateProductNotExists(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Product does not exist")));
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"f150f3ca-1a18-40e1-a01a-fad22724514a", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "f2672cf5-761e-4f5a-8fc2-b3264fc5dd0d"},
new[] {15.2, 12.2},
new[] {1.2, 2.3})]
public void UpdateCurrencyNotExists(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Currency does not exist")));
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {-5, 1.22},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new[] {"e5f89b1d-171f-4460-a2cc-18e1534b5bae", "526ea756-50da-486f-8a44-5e964f249c1e"},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {1.25, -1},
new[] {1.2, 2.3})]
public void UpdatePriceNotCorrect(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Price must be superior than 0")));
}
[Test]
[TestCase("01/01/2023",
"e2075166-6f2c-4172-8906-2f100a6a1456",
"0a891394-be17-473b-9924-eccaf6ce79ed",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {-5, 1.22},
new[] {1.2, 2.3})]
[TestCase("01/01/2023",
"51e6eec0-d9fd-47fc-830a-88d1e6638b88",
"9beb47ab-0def-437c-b510-02d8f9623ebb",
new string[] {},
new[] {"1a7d6616-dfd1-47c8-ba42-2b12e71c43af", "1a7d6616-dfd1-47c8-ba42-2b12e71c43af"},
new[] {1.25, -1},
new[] {1.2, 2.3})]
public void UpdateNoProduct(DateTime date, string idPurchase, string idUser, string[] products, string[] currencies, double[] prices, double[] quantities)
{
var purchaseToTest = Common.GetPurchaseDto(date, products.ToList(), currencies.ToList(), prices.ToList(), quantities.ToList());
purchaseToTest.id = Guid.Parse(idPurchase);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Update(Guid.Parse(idUser), purchaseToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("No product selected")));
}
[Test]
[TestCase("0a891394-be17-473b-9924-eccaf6ce79ed",
"01/01/2022",
"\nPomme de Terre Monalisa\n1 × 2.5 kg\n3.90 €\n \n\nAubergine\n1 × 400 g\n2.20 €\n \n\nCarottes\n1 × 1 kg\n2.20 €\n \n\nOignons Jaune\n1 × 500 g\n1.40 €\n \n\nPotimarron\n2 × 1.2 kg\n7.60 €\n \n\nPersil\n1 × 1\n1.40 €\n \n\nPatate Douce\n2 × 500 g\n5.60 €\n \nEARL LA POMME DORET\n \n\nPoire Conference\n1 × 1 kg\n2.20 €\n \n\nPomme Golden\n1 × 1 kg\n2.00 €\n \nEARL BERGERIE DE BAISENAZ\n \n\nFlan de Brebis Vanille\n3 × (2 × 12.5 cL)\n8.16 €\n \n\nYaourt de Brebis Fraise\n1 × (2 × 125 g)\n2.60 €\n \n\nYaourt de Brebis Fruits Des Bois\n1 × (2 × 125 g)\n2.60 €\n \nGoûter Desserts\n \n\nFarine de Blé T65 Label Rouge\n1 × (1 × 1 kg)\n2.00 €\n \n\nFarine de Blé T80 Bio\n1 × (1 × 1 kg)\n2.40 €\n \n\nSucette Chocolat Au Lait\n1 × 15 g\n1.50 €\n \n\nTablette de Chocolat Lait Afrique\n1 × (1 × 100 g)\n5.50 €\n \nGAEC les Maillets\n \n\nFv- Le Frais de Vache\n1 × 170 g\n2.00 €",
0)]
[TestCase("0a891394-be17-473b-9924-eccaf6ce79ed",
"01/01/2022",
"\nchou vert\n1 × 2.5 kg\n3.90 €\n \n\ntomate de saison\n1 × 400 g\n2.20 €\n \n\nCarottes\n1 × 1 kg\n2.20 €\n \n\nOignons Jaune\n1 × 500 g\n1.40 €\n \n\nPotimarron\n2 × 1.2 kg\n7.60 €\n \n\nPersil\n1 × 1\n1.40 €\n \n\nPatate Douce\n2 × 500 g\n5.60 €\n \nEARL LA POMME DORET\n \n\nPoire Conference\n1 × 1 kg\n2.20 €\n \n\nPomme Golden\n1 × 1 kg\n2.00 €\n \nEARL BERGERIE DE BAISENAZ\n \n\nFlan de Brebis Vanille\n3 × (2 × 12.5 cL)\n8.16 €\n \n\nYaourt de Brebis Fraise\n1 × (2 × 125 g)\n2.60 €\n \n\nYaourt de Brebis Fruits Des Bois\n1 × (2 × 125 g)\n2.60 €\n \nGoûter Desserts\n \n\nFarine de Blé T65 Label Rouge\n1 × (1 × 1 kg)\n2.00 €\n \n\nFarine de Blé T80 Bio\n1 × (1 × 1 kg)\n2.40 €\n \n\nSucette Chocolat Au Lait\n1 × 15 g\n1.50 €\n \n\nTablette de Chocolat Lait Afrique\n1 × (1 × 100 g)\n5.50 €\n \nGAEC les Maillets\n \n\nFv- Le Frais de Vache\n1 × 170 g\n2.00 €",
2)]
public async Task PurchaseLaRuche(string idUser, DateTime datePurchase, string command, int productWaited) {
PurchaseLaRucheDto purchaseLaRucheDto = Common.GetPurchaseLaRucheDto(datePurchase, command);
var result = await _service.ImportLaRuchePurchase(Guid.Parse(idUser), purchaseLaRucheDto);
Assert.IsTrue(_context.Object.Purchases.Any(p => p.id == result.id));
Assert.AreEqual(_context.Object.Purchases.First(p => p.id == result.id).products.Count(), productWaited);
}
}
}

View File

@ -0,0 +1,102 @@
using Moq;
using GiecChallenge.Services;
using Microsoft.Extensions.Logging;
using AutoMapper;
using GiecChallenge.Models;
using GiecChallenge.Profiles;
using Microsoft.Extensions.Configuration;
using System.Text;
namespace GiecChallenge.Tests
{
public class UserServiceTest
{
private Mock<ILogger<UserService>> _logger = null!;
private Mock<GiecChallengeContext> _context = null!;
private IConfiguration _configuration = null!;
private UserService _service = null!;
private List<UserDto> _allUsersDTO = null!;
[SetUp]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new UserProfile());
});
IMapper mapper = config.CreateMapper();
_logger = new Mock<ILogger<UserService>>();
var inMemorySettings = new Dictionary<string, string?> {
{"PasswordHash", "udr576eozuQkiLiLjpPJ"},
{"JWT:Secret", "YcJ=OB0%uFr$Q8sT<(o'"},
{"JWT:ValidIssuer", "http://localhost"},
{"JWT:ValidAudience", "http://localhost"}
};
_configuration = new ConfigurationBuilder().AddInMemoryCollection(inMemorySettings).Build();
_context = Common.GetContext();
_context.Setup(g => g.Users).Returns(Common.GetMockDbSet<User>(Common.GetUsers()).Object);
_context.Setup(g => g.Languages).Returns(Common.GetMockDbSet<Language>(Common.GetLanguages()).Object);
_context.Setup(g => g.UserGroups).Returns(Common.GetMockDbSet<UserGroup>(Common.GetUserGroups()).Object);
_service = new UserService(_logger.Object, mapper, _context.Object, _configuration);
}
[Test]
[TestCase("email@email.com", "toto1", "FR")]
[TestCase("email2@email.com", "toto3", "EN")]
public async Task Register(string email, string password, string language)
{
var userToTest = Common.GetUserDto(email, password, language);
await _service.Register(userToTest);
Assert.IsTrue(_context.Object.Users.Any(u => u.email == email));
}
[Test]
[TestCase("email@email.com", "toto1", "DK")]
[TestCase("email2@email.com", "toto3", "CN")]
public void RegisterLanguageNotExists(string email, string password, string language)
{
var userToTest = Common.GetUserDto(email, password, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Register(userToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Language does not exist")));
}
[Test]
[TestCase("toto@toto.com", "toto1", "FR")]
[TestCase("toto1@toto.com", "toto3", "EN")]
public void RegisterAlreadyExist(string email, string password, string language)
{
var userToTest = Common.GetUserDto(email, password, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Register(userToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("User already exist")));
}
[Test]
[TestCase("toto@toto.com", "password1", "FR")]
[TestCase("toto1@toto.com", "password2", "EN")]
public async Task Login(string email, string password, string language)
{
var userToTest = Common.GetUserDto(email, password, language);
var result = await _service.Login(userToTest);
Assert.IsTrue(_context.Object.Users.Any(u => u.email == email));
}
[Test]
[TestCase("toto@toto.com", "toto1", "FR")]
[TestCase("toto1@toto.com", "toto2", "FR")]
[TestCase("toto1@toto.com", "password1", "FR")]
[TestCase("toto@toto.com", "password2", "FR")]
public void LoginNotExist(string email, string password, string language)
{
var userToTest = Common.GetUserDto(email, password, language);
var ex = Assert.ThrowsAsync<Exception>(async () => await _service.Login(userToTest));
Assert.That(ex!.Message, Is.EqualTo(string.Concat("Email or password is incorrect")));
}
}
}

View File

@ -0,0 +1 @@
global using NUnit.Framework;

BIN
backend/GiecChallenge/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
GiecChallenge.test

View File

@ -0,0 +1,110 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class AlimentController : ControllerBase
{
private readonly ILogger<AlimentController> _logger;
private readonly IAlimentRepository _alimentRepository;
public AlimentController(ILogger<AlimentController> logger,
IAlimentRepository alimentRepository)
{
_logger = logger;
_alimentRepository = alimentRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _alimentRepository.GetAllAliments());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(string id)
{
try {
return Ok(await _alimentRepository.GetAliment(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{name}")]
public async Task<IActionResult> GetByName(string name)
{
try {
return Ok(await _alimentRepository.GetAliments(name.ToLower()));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(AlimentDto aliment)
{
try {
await _alimentRepository.Create(aliment);
return Ok(new { message = "Aliment created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost("full")]
public async Task<IActionResult> FullPost(List<AlimentDto> aliments)
{
try {
foreach (AlimentDto aliment in aliments)
await _alimentRepository.Create(aliment);
return Ok(new { message = "Aliments created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update(AlimentDto aliment)
{
try {
await _alimentRepository.Update(aliment);
return Ok(new { message = "Aliment updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut("full")]
public async Task<IActionResult> UpdateFull(List<AlimentDto> aliments)
{
try {
foreach (AlimentDto aliment in aliments) {
try {
await _alimentRepository.Update(aliment);
}
catch {
await _alimentRepository.Create(aliment);
}
}
return Ok(new { message = "Aliments updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
}

View File

@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class CurrencyController : ControllerBase
{
private readonly ILogger<CurrencyController> _logger;
private readonly ICurrencyRepository _currencyRepository;
public CurrencyController(ILogger<CurrencyController> logger,
ICurrencyRepository currencyRepository)
{
_logger = logger;
_currencyRepository = currencyRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _currencyRepository.GetAllCurrencies());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("iso/{id}")]
public async Task<IActionResult> GetByIso(string ISOCode)
{
try {
return Ok(await _currencyRepository.GetCurrencyByISO(ISOCode));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(Guid id)
{
try {
return Ok(await _currencyRepository.GetCurrency(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{language}/{name}")]
public async Task<IActionResult> GetByName(string name, string language)
{
try {
return Ok(await _currencyRepository.GetCurrencies(name.ToLower(), language));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(CurrencyDto currency)
{
try {
await _currencyRepository.Create(currency);
return Ok(new { message = "Currency created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update(Guid id, CurrencyDto currency)
{
try {
await _currencyRepository.Update(id, currency);
return Ok(new { message = "Currency updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
}

View File

@ -0,0 +1,78 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class GroupController : ControllerBase
{
private readonly ILogger<GroupController> _logger;
private readonly IGroupRepository _groupRepository;
public GroupController(ILogger<GroupController> logger,
IGroupRepository userRepository)
{
_logger = logger;
_groupRepository = userRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _groupRepository.GetAllGroups());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(Guid id)
{
try {
return Ok(await _groupRepository.GetGroup(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{language}/{name}")]
public async Task<IActionResult> GetByName(string name, string language)
{
try {
return Ok(await _groupRepository.GetGroups(name.ToLower(), language));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(GroupDto product)
{
try {
await _groupRepository.Create(product);
return Ok(new { message = "Group created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update(Guid id, GroupDto product)
{
try {
await _groupRepository.Update(id, product);
return Ok(new { message = "Group updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
}

View File

@ -0,0 +1,81 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class LanguageController : ControllerBase
{
private readonly ILogger<LanguageController> _logger;
private readonly ILanguageRepository _languageRepository;
public LanguageController(ILogger<LanguageController> logger,
ILanguageRepository languageRepository)
{
_logger = logger;
_languageRepository = languageRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _languageRepository.GetAllLanguages());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(Guid id)
{
try {
return Ok(await _languageRepository.GetLanguage(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{name}")]
public async Task<IActionResult> GetByName(string name, string language)
{
try {
return Ok(await _languageRepository.GetLanguages(name.ToLower(), language));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(LanguageDto language)
{
try {
await _languageRepository.Create(language);
return Ok(new { message = "Language created" });
}
catch (Exception ex) {
return Ok(new { message = ex.Message });
}
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(string id, LanguageDto language)
{
try {
if (Guid.TryParse(id, out Guid result)) {
await _languageRepository.Update(result, language);
return Ok(new { message = "Language updated" });
}
return Ok(new { message = "Id is not in good format" });
}
catch (Exception ex) {
return Ok(new { message = ex.Message });
}
}
}

View File

@ -0,0 +1,145 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class ProductController : ControllerBase
{
private readonly ILogger<ProductController> _logger;
private readonly IProductRepository _productRepository;
private Guid _userId {get; set;}
public ProductController(ILogger<ProductController> logger,
IProductRepository productRepository)
{
_logger = logger;
_productRepository = productRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _productRepository.GetAllProducts());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(Guid id)
{
try {
return Ok(await _productRepository.GetProduct(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{language}/{name}")]
public async Task<IActionResult> GetByName(string name, string language)
{
try {
var result = await _productRepository.GetProducts(name.ToLower(), language);
return Ok(result);
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("group/{groupId}")]
public async Task<IActionResult> GetByGroup(string groupId)
{
try {
return Ok(await _productRepository.GetProductsByGroup(groupId));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("subgroup/{subGroupId}")]
public async Task<IActionResult> GetBySubGroup(string subGroupId)
{
try {
return Ok(await _productRepository.GetProductsBySubGroup(subGroupId));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(ProductDto product)
{
try {
await _productRepository.Create(product);
return Ok(new { message = "Product created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update(Guid id, ProductDto product)
{
try {
await _productRepository.Update(id, product);
return Ok(new { message = "Product updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost("translation")]
public async Task<IActionResult> Post(ProductUserTranslationDTO translationDTO)
{
try {
await _productRepository.CreateTranslation(translationDTO);
return Ok(new { message = "Translation created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut("translation")]
public async Task<IActionResult> UpdateTranslation(ProductUserTranslationDTO translationDTO)
{
try {
await _productRepository.UpdateTranslation(translationDTO, _userId);
return Ok(new { message = "Translation deleted" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpDelete("translation")]
public async Task<IActionResult> DeleteTranslation(ProductUserTranslationDTO translationDTO)
{
try {
await _productRepository.DeleteTranslation(translationDTO, _userId);
return Ok(new { message = "Translation deleted" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
private void GetUserId() {
if (!Guid.TryParse(User.FindFirst(ClaimTypes.NameIdentifier)?.Value, out Guid userId))
throw new Exception("Not authorized");
this._userId = userId;
}
}

View File

@ -0,0 +1,154 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using GiecChallenge.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Cors;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class PurchaseController : ControllerBase
{
private readonly ILogger<PurchaseController> _logger;
private readonly IPurchaseRepository _purchaseRepository;
private Guid _userId {get; set;}
public PurchaseController(ILogger<PurchaseController> logger,
IPurchaseRepository purchaseRepository)
{
_logger = logger;
_purchaseRepository = purchaseRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
GetUserId();
return Ok(await _purchaseRepository.GetAll(_userId));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(string id)
{
try {
GetUserId();
if (Guid.TryParse(id, out Guid purchaseIdGuid)) {
return Ok(await _purchaseRepository.Get(_userId, purchaseIdGuid));
}
return StatusCode(500, new { Message = "Not a valid ID" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{dateBegin}/{dateEnd}")]
public async Task<IActionResult> GetBetweenDate(string dateBegin, string dateEnd)
{
try {
GetUserId();
return Ok(await _purchaseRepository.GetBetweenDate(_userId, DateTime.ParseExact(dateBegin, "dd-MM-yyyy", null), DateTime.ParseExact(dateEnd + " 23:59:59", "dd-MM-yyyy HH:mm:ss", null)));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("CO2/{dateBegin}/{dateEnd}")]
public async Task<IActionResult> GetCO2BetweenDate(string dateBegin, string dateEnd)
{
try {
GetUserId();
return Ok(await _purchaseRepository.GetCO2BetweenDate(_userId, DateTime.ParseExact(dateBegin, "dd-MM-yyyy", null), DateTime.ParseExact(dateEnd + " 23:59:59", "dd-MM-yyyy HH:mm:ss", null)));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(PurchaseDto purchaseDto)
{
try {
GetUserId();
await _purchaseRepository.Create(_userId, purchaseDto);
return Ok(new { message = "Purchase created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update([FromBody] PurchaseDto purchaseDto)
{
try {
GetUserId();
await _purchaseRepository.Update(_userId, purchaseDto);
return Ok(new { message = "Purchase updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpDelete("{purchaseId}")]
public async Task<IActionResult> Delete(string purchaseId)
{
try {
GetUserId();
if (Guid.TryParse(purchaseId, out Guid purchaseIdGuid)) {
await _purchaseRepository.Delete(_userId, purchaseIdGuid);
return Ok(new { message = "Purchase deleted" });
}
return StatusCode(500, new { Message = "Not a valid ID" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpDelete("line/{purchaseLineId}")]
public async Task<IActionResult> DeleteLine(string purchaseLineId)
{
try {
GetUserId();
if (Guid.TryParse(purchaseLineId, out Guid purchaseLineIdGuid)) {
await _purchaseRepository.DeleteLine(_userId, purchaseLineIdGuid);
return Ok(new { message = "Purchase line deleted" });
}
return StatusCode(500, new { Message = "Not a valid ID" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
[Route("laruche")]
public async Task<IActionResult> PostLaRuche(PurchaseLaRucheDto command)
{
try {
GetUserId();
return Ok(await _purchaseRepository.ImportLaRuchePurchase(_userId, command));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
private void GetUserId() {
if (!Guid.TryParse(User.FindFirst(ClaimTypes.NameIdentifier)?.Value, out Guid userId))
throw new Exception("Not authorized");
this._userId = userId;
}
}

View File

@ -0,0 +1,78 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[Authorize]
[Route("[controller]")]
public class SubGroupController : ControllerBase
{
private readonly ILogger<SubGroupController> _logger;
private readonly ISubGroupRepository _subGroupRepository;
public SubGroupController(ILogger<SubGroupController> logger,
ISubGroupRepository subgroupRepository)
{
_logger = logger;
_subGroupRepository = subgroupRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
try {
return Ok(await _subGroupRepository.GetAllSubGroups());
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetByCode(Guid id)
{
try {
return Ok(await _subGroupRepository.GetSubGroup(id));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpGet("name/{language}/{name}")]
public async Task<IActionResult> GetByName(string language, string name)
{
try {
return Ok(await _subGroupRepository.GetSubGroups(name.ToLower(), language));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost]
public async Task<IActionResult> Post(SubGroupDto subgroup)
{
try {
await _subGroupRepository.Create(subgroup);
return Ok(new { message = "SubGroup created" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPut]
public async Task<IActionResult> Update(Guid id, SubGroupDto subgroup)
{
try {
await _subGroupRepository.Update(id, subgroup);
return Ok(new { message = "SubGroup updated" });
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
}

View File

@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Mvc;
using GiecChallenge.Services;
using GiecChallenge.Models;
using Microsoft.AspNetCore.Authorization;
namespace GiecChallenge.Controllers;
[ApiController]
[AllowAnonymous]
[Route("[controller]")]
public class UserController : ControllerBase
{
private readonly ILogger<UserController> _logger;
private readonly IUserRepository _userRepository;
public UserController(ILogger<UserController> logger,
IUserRepository userRepository)
{
_logger = logger;
_userRepository = userRepository;
}
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login(UserDto userDto)
{
try {
return Ok(await _userRepository.Login(userDto));
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
[HttpPost("register")]
[AllowAnonymous]
public async Task<IActionResult> Register(UserDto userDto)
{
try {
await _userRepository.Register(userDto);
return Ok();
}
catch (Exception ex) {
return StatusCode(500, new { Message = ex.Message });
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
Pomme de Terre Monalisa
1 × 2.5 kg
3.90 €
Aubergine
1 × 400 g
2.20 €
Carottes
1 × 1 kg
2.20 €
Oignons Jaune
1 × 500 g
1.40 €
Potimarron
2 × 1.2 kg
7.60 €
Persil
1 × 1
1.40 €
Patate Douce
2 × 500 g
5.60 €
EARL LA POMME DORET
Poire Conference
1 × 1 kg
2.20 €
Pomme Golden
1 × 1 kg
2.00 €
EARL BERGERIE DE BAISENAZ
Flan de Brebis Vanille
3 × (2 × 12.5 cL)
8.16 €
Yaourt de Brebis Fraise
1 × (2 × 125 g)
2.60 €
Yaourt de Brebis Fruits Des Bois
1 × (2 × 125 g)
2.60 €
Goûter Desserts
Farine de Blé T65 Label Rouge
1 × (1 × 1 kg)
2.00 €
Farine de Blé T80 Bio
1 × (1 × 1 kg)
2.40 €
Sucette Chocolat Au Lait
1 × 15 g
1.50 €
Tablette de Chocolat Lait Afrique
1 × (1 × 100 g)
5.50 €
GAEC les Maillets
Fv- Le Frais de Vache
1 × 170 g
2.00 €

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
ENV ASPNETCORE_ENVIRONMENT Docker
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
ENV ASPNETCORE_ENVIRONMENT Docker
WORKDIR /src-backend
COPY ./backend/GiecChallenge/GiecChallenge.csproj .
RUN dotnet restore GiecChallenge.csproj
COPY ./backend/GiecChallenge .
RUN dotnet build GiecChallenge.csproj -c Docker -o /app/build
FROM build AS publish
RUN dotnet publish GiecChallenge.csproj -c Docker -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "GiecChallenge.dll"]

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Build.Containers" Version="0.2.7" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,686 @@
// <auto-generated />
using System;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace GiecChallenge.Migrations
{
[DbContext(typeof(GiecChallengeContext))]
[Migration("20230103180752_FieldsMissing")]
partial class FieldsMissing
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("dateBegin")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("dateEnd")
.HasColumnType("timestamp without time zone");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productid");
b.HasIndex("userid");
b.ToTable("CarbonLoans");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Currencies");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("languageid");
b.ToTable("CurrencyLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Languages");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("names")
.HasColumnType("uuid");
b.Property<Guid>("usedToTranlateLanguage")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("names");
b.HasIndex("usedToTranlateLanguage");
b.ToTable("LanguageLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<double>("CO2")
.HasColumnType("double precision");
b.Property<string>("CO2Unit")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Discriminator")
.IsRequired()
.HasColumnType("text");
b.Property<int>("amortization")
.HasColumnType("integer");
b.Property<Guid>("subgroupid")
.HasColumnType("uuid");
b.Property<double>("water")
.HasColumnType("double precision");
b.Property<string>("waterUnit")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("subgroupid");
b.ToTable("Products");
b.HasDiscriminator<string>("Discriminator").HasValue("Product");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.HasKey("id");
b.ToTable("ProductGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productgroupid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("languageid");
b.HasIndex("productgroupid");
b.ToTable("ProductGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("Productid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("Productid");
b.HasIndex("languageid");
b.ToTable("ProductLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<double>("price")
.HasColumnType("double precision");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("purchaseid")
.HasColumnType("uuid");
b.Property<double>("quantity")
.HasColumnType("double precision");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("productid");
b.HasIndex("purchaseid");
b.ToTable("ProductPurchases");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("Groupeid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("Groupeid");
b.ToTable("ProductSubGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("ProductSubGroupid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("ProductSubGroupid");
b.HasIndex("languageid");
b.ToTable("ProductSubGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productid");
b.HasIndex("userid");
b.ToTable("ProductUserTranslations");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("datePurchase")
.HasColumnType("timestamp without time zone");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("userid");
b.ToTable("Purchases");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("creationDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("email")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("favoriteLanguageid")
.HasColumnType("uuid");
b.Property<byte[]>("hash")
.IsRequired()
.HasColumnType("bytea");
b.Property<string>("password")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("favoriteLanguageid");
b.ToTable("Users");
});
modelBuilder.Entity("GiecChallenge.Models.UserGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("UserGroups");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("userGroupid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("userGroupid");
b.HasIndex("userid");
b.ToTable("UserInGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Aliment", b =>
{
b.HasBaseType("GiecChallenge.Models.Product");
b.Property<string>("ciqual")
.IsRequired()
.HasColumnType("text");
b.HasDiscriminator().HasValue("Aliment");
});
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("product");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany("names")
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "languageToChange")
.WithMany("names")
.HasForeignKey("names")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany("usedToTranlateLanguage")
.HasForeignKey("usedToTranlateLanguage")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("languageToChange");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", "subgroup")
.WithMany()
.HasForeignKey("subgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("subgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.ProductGroup", "productgroup")
.WithMany("names")
.HasForeignKey("productgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("productgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Product", null)
.WithMany("names")
.HasForeignKey("Productid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany()
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Purchase", "purchase")
.WithMany("products")
.HasForeignKey("purchaseid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("product");
b.Navigation("purchase");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.HasOne("GiecChallenge.Models.ProductGroup", "Groupe")
.WithMany()
.HasForeignKey("Groupeid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Groupe");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", null)
.WithMany("names")
.HasForeignKey("ProductSubGroupid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("product");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.HasOne("GiecChallenge.Models.Language", "favoriteLanguage")
.WithMany()
.HasForeignKey("favoriteLanguageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("favoriteLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.HasOne("GiecChallenge.Models.UserGroup", "userGroup")
.WithMany()
.HasForeignKey("userGroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany("groups")
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("user");
b.Navigation("userGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Navigation("names");
b.Navigation("usedToTranlateLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Navigation("products");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Navigation("groups");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GiecChallenge.Migrations
{
/// <inheritdoc />
public partial class FieldsMissing : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@ -0,0 +1,700 @@
// <auto-generated />
using System;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace GiecChallenge.Migrations
{
[DbContext(typeof(GiecChallengeContext))]
[Migration("20230128184437_ColumnsForLoan")]
partial class ColumnsForLoan
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("dateBegin")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("dateEnd")
.HasColumnType("timestamp without time zone");
b.Property<Guid>("productPurchaseid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productPurchaseid");
b.HasIndex("userid");
b.ToTable("CarbonLoans");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Currencies");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("languageid");
b.ToTable("CurrencyLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Languages");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("names")
.HasColumnType("uuid");
b.Property<Guid>("usedToTranlateLanguage")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("names");
b.HasIndex("usedToTranlateLanguage");
b.ToTable("LanguageLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<double>("CO2")
.HasColumnType("double precision");
b.Property<string>("CO2Unit")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Discriminator")
.IsRequired()
.HasColumnType("text");
b.Property<int>("amortization")
.HasColumnType("integer");
b.Property<Guid>("subgroupid")
.HasColumnType("uuid");
b.Property<double>("water")
.HasColumnType("double precision");
b.Property<string>("waterUnit")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("subgroupid");
b.ToTable("Products");
b.HasDiscriminator<string>("Discriminator").HasValue("Product");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.HasKey("id");
b.ToTable("ProductGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productgroupid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("languageid");
b.HasIndex("productgroupid");
b.ToTable("ProductGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("Productid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("Productid");
b.HasIndex("languageid");
b.ToTable("ProductLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<double>("CO2Cost")
.HasColumnType("double precision");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<double>("price")
.HasColumnType("double precision");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("purchaseid")
.HasColumnType("uuid");
b.Property<double>("quantity")
.HasColumnType("double precision");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("productid");
b.HasIndex("purchaseid");
b.ToTable("ProductPurchases");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("Groupeid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("Groupeid");
b.ToTable("ProductSubGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("ProductSubGroupid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("ProductSubGroupid");
b.HasIndex("languageid");
b.ToTable("ProductSubGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productid");
b.HasIndex("userid");
b.ToTable("ProductUserTranslations");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("datePurchase")
.HasColumnType("timestamp without time zone");
b.Property<Guid?>("initialPurchaseid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("initialPurchaseid");
b.HasIndex("userid");
b.ToTable("Purchases");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("creationDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("email")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("favoriteLanguageid")
.HasColumnType("uuid");
b.Property<byte[]>("hash")
.IsRequired()
.HasColumnType("bytea");
b.Property<string>("password")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("favoriteLanguageid");
b.ToTable("Users");
});
modelBuilder.Entity("GiecChallenge.Models.UserGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("UserGroups");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("userGroupid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("userGroupid");
b.HasIndex("userid");
b.ToTable("UserInGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Aliment", b =>
{
b.HasBaseType("GiecChallenge.Models.Product");
b.Property<string>("ciqual")
.IsRequired()
.HasColumnType("text");
b.HasDiscriminator().HasValue("Aliment");
});
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.HasOne("GiecChallenge.Models.ProductPurchase", "productPurchase")
.WithMany()
.HasForeignKey("productPurchaseid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("productPurchase");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany("names")
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "languageToChange")
.WithMany("names")
.HasForeignKey("names")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany("usedToTranlateLanguage")
.HasForeignKey("usedToTranlateLanguage")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("languageToChange");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", "subgroup")
.WithMany()
.HasForeignKey("subgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("subgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.ProductGroup", "productgroup")
.WithMany("names")
.HasForeignKey("productgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("productgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Product", null)
.WithMany("names")
.HasForeignKey("Productid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany()
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Purchase", "purchase")
.WithMany("products")
.HasForeignKey("purchaseid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("product");
b.Navigation("purchase");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.HasOne("GiecChallenge.Models.ProductGroup", "Groupe")
.WithMany()
.HasForeignKey("Groupeid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Groupe");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", null)
.WithMany("names")
.HasForeignKey("ProductSubGroupid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("product");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.HasOne("GiecChallenge.Models.Purchase", "initialPurchase")
.WithMany()
.HasForeignKey("initialPurchaseid");
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("initialPurchase");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.HasOne("GiecChallenge.Models.Language", "favoriteLanguage")
.WithMany()
.HasForeignKey("favoriteLanguageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("favoriteLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.HasOne("GiecChallenge.Models.UserGroup", "userGroup")
.WithMany()
.HasForeignKey("userGroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany("groups")
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("user");
b.Navigation("userGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Navigation("names");
b.Navigation("usedToTranlateLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Navigation("products");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Navigation("groups");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,104 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GiecChallenge.Migrations
{
/// <inheritdoc />
public partial class ColumnsForLoan : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CarbonLoans_Products_productid",
table: "CarbonLoans");
migrationBuilder.RenameColumn(
name: "productid",
table: "CarbonLoans",
newName: "productPurchaseid");
migrationBuilder.RenameIndex(
name: "IX_CarbonLoans_productid",
table: "CarbonLoans",
newName: "IX_CarbonLoans_productPurchaseid");
migrationBuilder.AddColumn<Guid>(
name: "initialPurchaseid",
table: "Purchases",
type: "uuid",
nullable: true);
migrationBuilder.AddColumn<double>(
name: "CO2Cost",
table: "ProductPurchases",
type: "double precision",
nullable: false,
defaultValue: 0.0);
migrationBuilder.CreateIndex(
name: "IX_Purchases_initialPurchaseid",
table: "Purchases",
column: "initialPurchaseid");
migrationBuilder.AddForeignKey(
name: "FK_CarbonLoans_ProductPurchases_productPurchaseid",
table: "CarbonLoans",
column: "productPurchaseid",
principalTable: "ProductPurchases",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Purchases_Purchases_initialPurchaseid",
table: "Purchases",
column: "initialPurchaseid",
principalTable: "Purchases",
principalColumn: "id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CarbonLoans_ProductPurchases_productPurchaseid",
table: "CarbonLoans");
migrationBuilder.DropForeignKey(
name: "FK_Purchases_Purchases_initialPurchaseid",
table: "Purchases");
migrationBuilder.DropIndex(
name: "IX_Purchases_initialPurchaseid",
table: "Purchases");
migrationBuilder.DropColumn(
name: "initialPurchaseid",
table: "Purchases");
migrationBuilder.DropColumn(
name: "CO2Cost",
table: "ProductPurchases");
migrationBuilder.RenameColumn(
name: "productPurchaseid",
table: "CarbonLoans",
newName: "productid");
migrationBuilder.RenameIndex(
name: "IX_CarbonLoans_productPurchaseid",
table: "CarbonLoans",
newName: "IX_CarbonLoans_productid");
migrationBuilder.AddForeignKey(
name: "FK_CarbonLoans_Products_productid",
table: "CarbonLoans",
column: "productid",
principalTable: "Products",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -0,0 +1,697 @@
// <auto-generated />
using System;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace GiecChallenge.Migrations
{
[DbContext(typeof(GiecChallengeContext))]
partial class GiecChallengeContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("dateBegin")
.HasColumnType("timestamp without time zone");
b.Property<DateTime>("dateEnd")
.HasColumnType("timestamp without time zone");
b.Property<Guid>("productPurchaseid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productPurchaseid");
b.HasIndex("userid");
b.ToTable("CarbonLoans");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Currencies");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("languageid");
b.ToTable("CurrencyLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("ISOCode")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("Languages");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("names")
.HasColumnType("uuid");
b.Property<Guid>("usedToTranlateLanguage")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("names");
b.HasIndex("usedToTranlateLanguage");
b.ToTable("LanguageLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<double>("CO2")
.HasColumnType("double precision");
b.Property<string>("CO2Unit")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Discriminator")
.IsRequired()
.HasColumnType("text");
b.Property<int>("amortization")
.HasColumnType("integer");
b.Property<Guid>("subgroupid")
.HasColumnType("uuid");
b.Property<double>("water")
.HasColumnType("double precision");
b.Property<string>("waterUnit")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("subgroupid");
b.ToTable("Products");
b.HasDiscriminator<string>("Discriminator").HasValue("Product");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.HasKey("id");
b.ToTable("ProductGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productgroupid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("languageid");
b.HasIndex("productgroupid");
b.ToTable("ProductGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("Productid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("Productid");
b.HasIndex("languageid");
b.ToTable("ProductLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<double>("CO2Cost")
.HasColumnType("double precision");
b.Property<Guid>("currencyid")
.HasColumnType("uuid");
b.Property<double>("price")
.HasColumnType("double precision");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("purchaseid")
.HasColumnType("uuid");
b.Property<double>("quantity")
.HasColumnType("double precision");
b.HasKey("id");
b.HasIndex("currencyid");
b.HasIndex("productid");
b.HasIndex("purchaseid");
b.ToTable("ProductPurchases");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("Groupeid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("Groupeid");
b.ToTable("ProductSubGroups");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("ProductSubGroupid")
.HasColumnType("uuid");
b.Property<Guid>("languageid")
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("ProductSubGroupid");
b.HasIndex("languageid");
b.ToTable("ProductSubGroupLanguages");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("productid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("productid");
b.HasIndex("userid");
b.ToTable("ProductUserTranslations");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("datePurchase")
.HasColumnType("timestamp without time zone");
b.Property<Guid?>("initialPurchaseid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("initialPurchaseid");
b.HasIndex("userid");
b.ToTable("Purchases");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("creationDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("email")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("favoriteLanguageid")
.HasColumnType("uuid");
b.Property<byte[]>("hash")
.IsRequired()
.HasColumnType("bytea");
b.Property<string>("password")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.HasIndex("favoriteLanguageid");
b.ToTable("Users");
});
modelBuilder.Entity("GiecChallenge.Models.UserGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("name")
.IsRequired()
.HasColumnType("text");
b.HasKey("id");
b.ToTable("UserGroups");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.Property<Guid>("id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("userGroupid")
.HasColumnType("uuid");
b.Property<Guid>("userid")
.HasColumnType("uuid");
b.HasKey("id");
b.HasIndex("userGroupid");
b.HasIndex("userid");
b.ToTable("UserInGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Aliment", b =>
{
b.HasBaseType("GiecChallenge.Models.Product");
b.Property<string>("ciqual")
.IsRequired()
.HasColumnType("text");
b.HasDiscriminator().HasValue("Aliment");
});
modelBuilder.Entity("GiecChallenge.Models.CarbonLoan", b =>
{
b.HasOne("GiecChallenge.Models.ProductPurchase", "productPurchase")
.WithMany()
.HasForeignKey("productPurchaseid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("productPurchase");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.CurrencyLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany("names")
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.LanguageLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "languageToChange")
.WithMany("names")
.HasForeignKey("names")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany("usedToTranlateLanguage")
.HasForeignKey("usedToTranlateLanguage")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("languageToChange");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", "subgroup")
.WithMany()
.HasForeignKey("subgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("subgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.ProductGroup", "productgroup")
.WithMany("names")
.HasForeignKey("productgroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
b.Navigation("productgroup");
});
modelBuilder.Entity("GiecChallenge.Models.ProductLanguage", b =>
{
b.HasOne("GiecChallenge.Models.Product", null)
.WithMany("names")
.HasForeignKey("Productid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductPurchase", b =>
{
b.HasOne("GiecChallenge.Models.Currency", "currency")
.WithMany()
.HasForeignKey("currencyid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.Purchase", "purchase")
.WithMany("products")
.HasForeignKey("purchaseid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("currency");
b.Navigation("product");
b.Navigation("purchase");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.HasOne("GiecChallenge.Models.ProductGroup", "Groupe")
.WithMany()
.HasForeignKey("Groupeid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Groupe");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroupLanguage", b =>
{
b.HasOne("GiecChallenge.Models.ProductSubGroup", null)
.WithMany("names")
.HasForeignKey("ProductSubGroupid");
b.HasOne("GiecChallenge.Models.Language", "language")
.WithMany()
.HasForeignKey("languageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("language");
});
modelBuilder.Entity("GiecChallenge.Models.ProductUserTranslation", b =>
{
b.HasOne("GiecChallenge.Models.Product", "product")
.WithMany()
.HasForeignKey("productid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("product");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.HasOne("GiecChallenge.Models.Purchase", "initialPurchase")
.WithMany()
.HasForeignKey("initialPurchaseid");
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany()
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("initialPurchase");
b.Navigation("user");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.HasOne("GiecChallenge.Models.Language", "favoriteLanguage")
.WithMany()
.HasForeignKey("favoriteLanguageid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("favoriteLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.UserInGroup", b =>
{
b.HasOne("GiecChallenge.Models.UserGroup", "userGroup")
.WithMany()
.HasForeignKey("userGroupid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GiecChallenge.Models.User", "user")
.WithMany("groups")
.HasForeignKey("userid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("user");
b.Navigation("userGroup");
});
modelBuilder.Entity("GiecChallenge.Models.Currency", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Language", b =>
{
b.Navigation("names");
b.Navigation("usedToTranlateLanguage");
});
modelBuilder.Entity("GiecChallenge.Models.Product", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.ProductSubGroup", b =>
{
b.Navigation("names");
});
modelBuilder.Entity("GiecChallenge.Models.Purchase", b =>
{
b.Navigation("products");
});
modelBuilder.Entity("GiecChallenge.Models.User", b =>
{
b.Navigation("groups");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class Aliment : Product
{
[Required]
public string ciqual { get; set; } = default!;
 }

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class CarbonLoan
{
public Guid id { get; set; }
[Required]
public User user { get; set; } = new User();
[Required]
public ProductPurchase productPurchase { get; set; } = new ProductPurchase();
[Required]
public DateTime dateBegin { get; set; }
[Required]
public DateTime dateEnd { get; set; }
 }

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class Currency
{
public Guid id { get; set; }
[Required]
public string ISOCode { get; set; } = string.Empty;
[Required]
public List<CurrencyLanguage> names { get; set; } = new List<CurrencyLanguage>();
 }

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class CurrencyLanguage
{
public Guid id { get; set; }
[Required]
public Currency currency { get; set; } = new Currency();
[Required]
public Language language { get; set; } = new Language();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,24 @@
public class AlimentDto
{
public string nom_francais { get; set; } = string.Empty;
public string groupe { get; set; } = string.Empty;
public string ciqual_code { get; set; } = string.Empty;
public ImpactEnvironnementalAlimentDto impact_environnemental { get; set; } = new ImpactEnvironnementalAlimentDto();
 }
public class ImpactEnvironnementalAlimentDto
{
public ChangementClimatiqueDto changement_climatique { get; set; } = new ChangementClimatiqueDto();
public EpuisementEauDto epuisement_eau { get; set; } = new EpuisementEauDto();
}
public class ChangementClimatiqueDto {
public double synthese { get; set; }
public string unite { get; set; } = string.Empty;
}
public class EpuisementEauDto {
public double synthese { get; set; }
public string unite { get; set; } = string.Empty;
}

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
public class CurrencyDto
{
public Guid id { get; set; } = new Guid();
public string ISOCode { get; set; } = string.Empty;
public List<CurrencyNamesDto> names { get; set; } = new List<CurrencyNamesDto>();
public string language { get; set; } = "FR";
 }
public class CurrencyNamesDto
{
[Required]
public string name { get; set; } = string.Empty;
[Required]
public string language { get; set; } = string.Empty;
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
public class GroupDto
{
public Guid id { get; set; } = new Guid();
public List<GroupNamesDto> names { get; set; } = new List<GroupNamesDto>();
public string language { get; set; } = "FR";
 }
public class GroupNamesDto
{
[Required]
public string name { get; set; } = string.Empty;
[Required]
public string language { get; set; } = string.Empty;
}

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
public class LanguageDto
{
public Guid id { get; set; } = new Guid();
public string ISOCode { get; set; } = string.Empty;
public List<LanguageNamesDto> names { get; set; } = new List<LanguageNamesDto>();
public string language { get; set; } = "FR";
 }
public class LanguageNamesDto
{
[Required]
public string name { get; set; } = string.Empty;
[Required]
public string language { get; set; } = string.Empty;
}

View File

@ -0,0 +1,45 @@
using System.ComponentModel.DataAnnotations;
public class ProductDto
{
public Guid id {get; set;} = new Guid();
public List<ProductNamesDto> names { get; set; } = new List<ProductNamesDto>();
public string language { get; set; } = "FR";
public string group { get; set; } = string.Empty;
public double CO2 { get; set; }
public string CO2Unit { get; set; } = string.Empty;
public double water { get; set; }
public string waterUnit { get; set; } = string.Empty;
public int amortization { get; set; } = 0;
 }
public class ProductNamesDto
{
[Required]
public string name { get; set; } = string.Empty;
[Required]
public string language { get; set; } = string.Empty;
}
public class ProductUserTranslationDTO
{
public string id { get; set; } = string.Empty;
[Required]
public string user { get; set; } = string.Empty;
[Required]
public string product { get; set; } = string.Empty;
[Required]
public string name { get; set; } = string.Empty;
}

View File

@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductPurchaseDto
{
public string id { get; set; } = string.Empty;
public string translation { get; set; } = string.Empty!;
public string product { get; set; } = string.Empty!;
public string currencyIsoCode { get; set; } = string.Empty!;
public Guid? productId { get; set; }
public Double quantity { get; set; }
public Double price { get; set; }
public Double WaterCost { get; set; }
public Double CO2Cost { get; set; }
 }
public class PurchaseLaRucheImportReturnDto
{
public Guid id { get; set; }
public List<ProductPurchaseDto> productsToTranslate { get; set; } = new List<ProductPurchaseDto>();
}

View File

@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
namespace GiecChallenge.Models;
public class PurchaseDto
{
public Guid? id { get; set; } = Guid.Empty;
[Required]
public DateTime datePurchase { get; set; }
[Required]
public List<ProductPurchaseDto> products { get; set; } = new List<ProductPurchaseDto>();
public double CO2Cost { get; set; } = 0;
public double WaterCost { get; set; } = 0;
 }
public class PurchaseLaRucheDto
{
public DateTime datePurchase { get; set; }
public string command { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
public class SubGroupDto
{
public Guid id { get; set; } = new Guid();
public List<SubGroupNamesDto> names { get; set; } = new List<SubGroupNamesDto>();
[Required]
public string group { get; set; } = string.Empty;
public string language { get; set; } = "FR";
 }
public class SubGroupNamesDto
{
[Required]
public string name { get; set; } = string.Empty;
[Required]
public string language { get; set; } = string.Empty;
}

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class UserDto
{
[Required]
public string email { get; set; } = string.Empty;
[Required]
public string password { get; set; } = string.Empty;
public string language { get; set; } = string.Empty;
public string token { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class UserGroupDto
{
public Guid id { get; set; }
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,55 @@
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Models
{
public class GiecChallengeContext : DbContext
{
public GiecChallengeContext(DbContextOptions<GiecChallengeContext> options):base(options) {
base.Database.EnsureCreated();
}
public virtual void SetEntityStateModified(Purchase purchase)
{
base.Entry(purchase).State = EntityState.Modified;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Aliment>();
modelBuilder.Entity<CarbonLoan>();
modelBuilder.Entity<Currency>();
modelBuilder.Entity<CurrencyLanguage>();
modelBuilder.Entity<Language>();
modelBuilder.Entity<LanguageLanguage>();
modelBuilder.Entity<Product>();
modelBuilder.Entity<ProductGroup>();
modelBuilder.Entity<ProductGroupLanguage>();
modelBuilder.Entity<ProductLanguage>();
modelBuilder.Entity<ProductPurchase>();
modelBuilder.Entity<ProductSubGroup>();
modelBuilder.Entity<ProductSubGroupLanguage>();
modelBuilder.Entity<ProductUserTranslation>();
modelBuilder.Entity<Purchase>();
modelBuilder.Entity<User>();
modelBuilder.Entity<UserGroup>();
}
public virtual DbSet<Aliment> Aliments { get; set; } = null!;
public virtual DbSet<CarbonLoan> CarbonLoans { get; set; } = null!;
public virtual DbSet<Currency> Currencies { get; set; } = null!;
public virtual DbSet<CurrencyLanguage> CurrencyLanguages { get; set; } = null!;
public virtual DbSet<Language> Languages { get; set; } = null!;
public virtual DbSet<LanguageLanguage> LanguageLanguages { get; set; } = null!;
public virtual DbSet<Product> Products { get; set; } = null!;
public virtual DbSet<ProductGroup> ProductGroups { get; set; } = null!;
public virtual DbSet<ProductGroupLanguage> ProductGroupLanguages { get; set; } = null!;
public virtual DbSet<ProductLanguage> ProductLanguages { get; set; } = null!;
public virtual DbSet<ProductPurchase> ProductPurchases { get; set; } = null!;
public virtual DbSet<ProductSubGroup> ProductSubGroups { get; set; } = null!;
public virtual DbSet<ProductSubGroupLanguage> ProductSubGroupLanguages { get; set; } = null!;
public virtual DbSet<ProductUserTranslation> ProductUserTranslations { get; set; } = null!;
public virtual DbSet<Purchase> Purchases { get; set; } = null!;
public virtual DbSet<User> Users { get; set; } = null!;
public virtual DbSet<UserGroup> UserGroups { get; set; } = null!;
}
}

View File

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class Language
{
public Guid id { get; set; }
[Required]
public string ISOCode { get; set; } = string.Empty;
[Required]
[InverseProperty("languageToChange")]
public virtual List<LanguageLanguage> names { get; set; } = new List<LanguageLanguage>();
[Required]
[InverseProperty("language")]
public virtual List<LanguageLanguage> usedToTranlateLanguage { get; set; } = new List<LanguageLanguage>();
 }

View File

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class LanguageLanguage
{
public Guid id { get; set; }
[Required]
[ForeignKey("names")]
public Language languageToChange { get; set; } = new Language();
[Required]
[ForeignKey("usedToTranlateLanguage")]
public Language language { get; set; } = new Language();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
namespace GiecChallenge.Models;
public class Product
{
public Guid id { get; set; }
[Required]
public ProductSubGroup subgroup { get; set; } = new ProductSubGroup();
[Required]
public List<ProductLanguage> names { get; set; } = new List<ProductLanguage>();
[Required]
public double CO2 { get; set; }
[Required]
public string CO2Unit { get; set; } = string.Empty;
public double water { get; set; }
public string waterUnit { get; set; } = string.Empty;
[Required]
public int amortization { get; set; } = 0;
 }

View File

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductGroup
{
public Guid id { get; set; }
[Required]
public List<ProductGroupLanguage> names { get; set; } = new List<ProductGroupLanguage>();
 }

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductGroupLanguage
{
public Guid id { get; set; }
[Required]
public ProductGroup productgroup { get; set; } = new ProductGroup();
[Required]
public Language language { get; set; } = new Language();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductLanguage
{
public Guid id { get; set; }
[Required]
public Language language { get; set; } = new Language();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductPurchase
{
public Guid id { get; set; }
[Required]
public Purchase purchase { get; set; } = new Purchase();
[Required]
public Product product { get; set; } = new Product();
[Required]
public Currency currency { get; set; } = new Currency();
[Required]
public Double price { get; set; }
[Required]
public Double quantity { get; set; }
[Required]
public Double CO2Cost { get; set; }
 }

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductSubGroup
{
public Guid id { get; set; }
[Required]
public List<ProductSubGroupLanguage> names { get; set; } = new List<ProductSubGroupLanguage>();
[Required]
public ProductGroup Groupe { get; set; } = new ProductGroup();
 }

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductSubGroupLanguage
{
public Guid id { get; set; }
[Required]
public Language language { get; set; } = new Language();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class ProductUserTranslation
{
public Guid id { get; set; }
[Required]
public User user { get; set; } = new User();
[Required]
public Product product { get; set; } = new Product();
[Required]
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class Purchase
{
public Guid id { get; set; }
public DateTime datePurchase { get; set; }
[Required]
public User user { get; set; } = new User();
public List<ProductPurchase> products { get; set; } = new List<ProductPurchase>();
//Useful for loan
public Purchase? initialPurchase { get; set; }
 }

View File

@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GiecChallenge.Models;
public class User
{
public Guid id { get; set; }
[Required]
public string email { get; set; } = string.Empty;
[Required]
public string password { get; set; } = string.Empty;
public Language favoriteLanguage { get; set; } = new Language();
public DateTime creationDate { get; set; }
public byte[] hash { get; set; } = new byte[] {};
public List<UserInGroup> groups { get; set; } = new List<UserInGroup>();
 }

View File

@ -0,0 +1,8 @@
namespace GiecChallenge.Models;
public class UserGroup
{
public Guid id { get; set; }
public string name { get; set; } = string.Empty;
 }

View File

@ -0,0 +1,10 @@
namespace GiecChallenge.Models;
public class UserInGroup
{
public Guid id { get; set; }
public User user { get; set; } = new User();
public UserGroup userGroup { get; set; } = new UserGroup();
 }

View File

@ -0,0 +1,24 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class AlimentProfile : Profile
{
public AlimentProfile() {
CreateMap<Aliment, AlimentDto>().ForMember(dest => dest.ciqual_code, opt => { opt.MapFrom((s, d) => s.ciqual);})
.ForMember(dest => dest.nom_francais, opt => { opt.MapFrom((s, d) => s.names.FirstOrDefault(n => n.language.ISOCode == "FR")?.name);})
.ForMember(dest => dest.groupe, opt => { opt.MapFrom((s, d, destMember, context) => s.subgroup.names.FirstOrDefault(i => i.language == context.Items["language"])?.name);})
.ForPath(dest => dest.impact_environnemental.changement_climatique.synthese, opt => { opt.MapFrom(s => s.CO2);})
.ForPath(dest => dest.impact_environnemental.changement_climatique.unite, opt => { opt.MapFrom(s => s.CO2Unit);})
.ForPath(dest => dest.impact_environnemental.epuisement_eau.synthese, opt => { opt.MapFrom(s => s.water);})
.ForPath(dest => dest.impact_environnemental.epuisement_eau.unite, opt => { opt.MapFrom(s => s.waterUnit);});
CreateMap<AlimentDto, Aliment>().ForMember(dest => dest.ciqual, opt => { opt.MapFrom((s, d) => s.ciqual_code);})
.ForMember(dest => dest.CO2, opt => { opt.MapFrom((s, d) => s.impact_environnemental.changement_climatique.synthese);})
.ForMember(dest => dest.CO2Unit, opt => { opt.MapFrom((s, d) => s.impact_environnemental.changement_climatique.unite);})
.ForMember(dest => dest.water, opt => { opt.MapFrom((s, d) => s.impact_environnemental.epuisement_eau.synthese);})
.ForMember(dest => dest.waterUnit, opt => { opt.MapFrom((s, d) => s.impact_environnemental.epuisement_eau.unite);})
.ForMember(dest => dest.names, opt => { opt.MapFrom((s, d, destMember, context) => new List<ProductLanguage>() { new ProductLanguage() { name = s.nom_francais, language = (Language)context.Items["language"] }});});
}
}
}

View File

@ -0,0 +1,21 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class CurrencyProfile : Profile
{
public CurrencyProfile() {
CreateMap<Currency, CurrencyDto>().ForMember(dest => dest.names, opt => { opt.MapFrom((s, d) => s.names);})
.ForMember(dest => dest.language, opt => { opt.Ignore();});
CreateMap<CurrencyDto, Currency>().ForMember(dest => dest.names, opt => opt.Ignore())
.ForMember(dest => dest.id, opt => opt.Ignore());
CreateMap<CurrencyLanguage, CurrencyNamesDto>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d) => s.language.ISOCode);});
CreateMap<CurrencyNamesDto, CurrencyLanguage>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d, destMember, context) => (Language)context.Items["language"]);});
}
}
}

View File

@ -0,0 +1,21 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class GroupProfile : Profile
{
public GroupProfile() {
CreateMap<ProductGroup, GroupDto>().ForMember(dest => dest.names, opt => { opt.MapFrom((s, d) => s.names);})
.ForMember(dest => dest.language, opt => { opt.Ignore();});
CreateMap<GroupDto, ProductGroup>().ForMember(dest => dest.names, opt => opt.Ignore())
.ForMember(dest => dest.id, opt => opt.Ignore());
CreateMap<ProductGroupLanguage, GroupNamesDto>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d) => s.language.ISOCode);});
CreateMap<GroupNamesDto, ProductGroupLanguage>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d, destMember, context) => (Language)context.Items["language"]);});
}
}
}

View File

@ -0,0 +1,21 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class LanguageProfile : Profile
{
public LanguageProfile() {
CreateMap<Language, LanguageDto>().ForMember(dest => dest.names, opt => { opt.MapFrom((s, d) => s.names);})
.ForMember(dest => dest.language, opt => { opt.Ignore();});
CreateMap<LanguageDto, Language>().ForMember(dest => dest.names, opt => opt.Ignore())
.ForMember(dest => dest.id, opt => opt.Ignore());
CreateMap<LanguageLanguage, LanguageNamesDto>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d) => s.language.ISOCode);});
CreateMap<LanguageNamesDto, LanguageLanguage>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d, destMember, context) => (Language)context.Items["language"]);});
}
}
}

View File

@ -0,0 +1,29 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class ProductProfile : Profile
{
public ProductProfile() {
CreateMap<Product, ProductDto>().ForMember(dest => dest.id, opt => { opt.MapFrom((s, d) => s.id);})
.ForMember(dest => dest.names, opt => { opt.MapFrom((s, d) => s.names);})
.ForMember(dest => dest.group, opt => { opt.MapFrom((s, d, destMember, context) => s.subgroup.names.FirstOrDefault(i => i.language.ISOCode == d.language)?.name);});
CreateMap<ProductDto, Product>().ForMember(dest => dest.names, opt => opt.Ignore())
.ForMember(dest => dest.subgroup, opt => opt.Ignore());
CreateMap<ProductLanguage, ProductNamesDto>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d) => s.language.ISOCode);});
CreateMap<ProductNamesDto, ProductLanguage>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d, destMember, context) => (Language)context.Items["language"]);});
CreateMap<ProductUserTranslation, ProductUserTranslationDTO>().ForMember(dest => dest.product, opt => { opt.MapFrom((s, d) => s.product.id.ToString());})
.ForMember(dest => dest.user, opt => { opt.MapFrom((s, d) => s.user.id.ToString());});
CreateMap<ProductUserTranslationDTO, ProductUserTranslation>().ForMember(dest => dest.id, opt => { opt.Ignore();})
.ForMember(dest => dest.product, opt => { opt.Ignore();})
.ForMember(dest => dest.user, opt => { opt.Ignore(); });
}
}
}

View File

@ -0,0 +1,24 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class PurchaseProfile : Profile
{
public PurchaseProfile() {
CreateMap<Purchase, PurchaseDto>().ForMember(dest => dest.products, opt => { opt.Ignore();});
CreateMap<PurchaseDto, Purchase>().ForMember(dest => dest.user, opt => { opt.Ignore();})
.ForMember(dest => dest.products, opt => opt.Ignore());
CreateMap<ProductPurchase, ProductPurchaseDto>().ForMember(dest => dest.currencyIsoCode, opt => { opt.MapFrom((s, d) => s.currency.ISOCode);} )
.ForMember(dest => dest.product, opt => { opt.MapFrom((s, d, destMember, context) => s.product != null ? s.product.names.Any(n => n.language == (Language)context.Items["language"]) ? s.product.names.FirstOrDefault(n => n.language == (Language)context.Items["language"])?.name : s.product.names.FirstOrDefault(n => n.language.ISOCode == "FR")?.name : "");} )
.ForMember(dest => dest.productId, opt => { opt.MapFrom((s, d) => s.product?.id.ToString());} )
.ForMember(dest => dest.CO2Cost, opt => { opt.MapFrom((s, d) => s.product != null ? s.product.CO2 : 0);} )
.ForMember(dest => dest.WaterCost, opt => { opt.MapFrom((s, d) => s.product != null ? s.product.water : 0);} );
CreateMap<ProductPurchaseDto, ProductPurchase>().ForMember(dest => dest.id, opt => { opt.MapFrom((s, d) => !string.IsNullOrEmpty(s.id) ? Guid.Parse(s.id) : Guid.Empty );} )
.ForMember(dest => dest.product, opt => opt.Ignore() )
.ForMember(dest => dest.currency, opt => opt.Ignore() );
}
}
}

View File

@ -0,0 +1,23 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class SubGroupProfile : Profile
{
public SubGroupProfile() {
CreateMap<ProductSubGroup, SubGroupDto>().ForMember(dest => dest.names, opt => { opt.MapFrom((s, d) => s.names);})
.ForMember(dest => dest.language, opt => { opt.Ignore();})
.ForMember(dest => dest.group, opt => { opt.MapFrom((s, d) => s.Groupe.names.FirstOrDefault(n => n.language.ISOCode == d.language)?.name); });
CreateMap<SubGroupDto, ProductSubGroup>().ForMember(dest => dest.names, opt => opt.Ignore())
.ForMember(dest => dest.id, opt => opt.Ignore())
.ForMember(dest => dest.Groupe, opt => opt.Ignore());
CreateMap<ProductSubGroupLanguage, SubGroupNamesDto>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d) => s.language.ISOCode);});
CreateMap<SubGroupNamesDto, ProductSubGroupLanguage>().ForMember(dest => dest.name, opt => { opt.MapFrom((s, d) => s.name);})
.ForMember(dest => dest.language, opt => { opt.MapFrom((s, d, destMember, context) => (Language)context.Items["language"]);});
}
}
}

View File

@ -0,0 +1,19 @@
using AutoMapper;
using GiecChallenge.Models;
namespace GiecChallenge.Profiles {
public class UserProfile : Profile
{
public UserProfile() {
CreateMap<User, UserDto>().ForMember(dest => dest.token, opt => { opt.Ignore();})
.ForMember(dest => dest.password, opt => { opt.Ignore();});
CreateMap<UserDto, User>().ForMember(dest => dest.creationDate, opt => { opt.MapFrom((s, d) => DateTime.Now);})
.ForMember(dest => dest.id, opt => opt.Ignore());
CreateMap<UserGroup, UserGroupDto>().ForMember(dest => dest.id, opt => opt.Ignore() );
CreateMap<UserGroupDto, UserGroup>();
}
}
}

View File

@ -0,0 +1,110 @@
using Microsoft.EntityFrameworkCore;
using GiecChallenge.Models;
using GiecChallenge.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.HttpOverrides;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
ConfigurationManager configuration = builder.Configuration;
builder.Services.AddControllers(
options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);
builder.Services.AddEntityFrameworkNpgsql().AddDbContext<GiecChallengeContext>(opt =>
opt.UseNpgsql(builder.Configuration.GetConnectionString("PostgreSQL")));
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
builder.Services.AddCors(p =>
p.AddPolicy("CORSPolicy", x => x.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(_ => true)
.AllowCredentials())
);
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = configuration["JWT:ValidAudience"],
ValidIssuer = configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]!))
};
});
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
});
builder.Services.AddAuthorization();
addScoped();
var app = builder.Build();
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseRouting();
app.Use((ctx, next) =>
{
var headers = ctx.Response.Headers;
headers["Access-Control-Allow-Origin"] = configuration["OriginAllowed"];
headers["Access-Control-Allow-Credentials"] = "true";
headers["Access-Control-Allow-Headers"] = "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name";
headers["Access-Control-Allow-Methods"] = "POST,GET,PUT,PATCH,DELETE,OPTIONS";
headers["cc"] = "test";
return next();
});
app.UseCors("CORSPolicy");
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.MapSwagger();
app.Run();
void addScoped() {
builder.Services.AddScoped<IAlimentRepository, AlimentService>();
builder.Services.AddScoped<IProductRepository, ProductService>();
builder.Services.AddScoped<ICurrencyRepository, Currencieservice>();
builder.Services.AddScoped<IGroupRepository, GroupService>();
builder.Services.AddScoped<ISubGroupRepository, SubGroupService>();
builder.Services.AddScoped<ILanguageRepository, LanguageService>();
builder.Services.AddScoped<IUserRepository, UserService>();
builder.Services.AddScoped<IPurchaseRepository, PurchaseService>();
}

View File

@ -0,0 +1,44 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:39531",
"sslPort": 44382
}
},
"profiles": {
"GiecChallenge": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7021;http://localhost:5028",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Release",
"ASPNETCORE_URLS": "https://+:17021;http://+:17020",
"ASPNETCORE_HTTPS_PORT": "17021"
},
"httpPort": 17020,
"useSSL": true,
"sslPort": 17021
}
}
}

View File

@ -0,0 +1,127 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface IAlimentRepository
{
Task<List<AlimentDto>> GetAllAliments();
Task<AlimentDto?> GetAliment(string code);
Task<List<AlimentDto>> GetAliments(string name);
Task Create(AlimentDto alimentDto);
Task Update(AlimentDto aliment);
}
public class AlimentService : IAlimentRepository
{
private readonly ILogger<AlimentService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public AlimentService(ILogger<AlimentService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<AlimentDto>> GetAllAliments()
{
var languageFR = await getLanguageFR();
var allAliments = await _context.Aliments.Include(b => b.names).Include(b => b.subgroup).Include(b => b.subgroup.names).ToListAsync();
return _mapper.Map<List<Aliment>, List<AlimentDto>>(allAliments, opts: opt => opt.Items["language"] = languageFR);
}
public async Task<AlimentDto?> GetAliment(string code)
{
var languageFR = await getLanguageFR();
Aliment? aliment = await this._context.Aliments.Include(b => b.names).Include(b => b.subgroup).Include(b => b.subgroup.names).FirstOrDefaultAsync(al => al.ciqual == code);
if (aliment == null)
throw new Exception(string.Concat(code, " does not exist"));
return _mapper.Map<Aliment, AlimentDto>(aliment, opts: opt => opt.Items["language"] = languageFR);
}
public async Task<List<AlimentDto>> GetAliments(string name)
{
var languageFR = await getLanguageFR();
var result = await _context.ProductUserTranslations.Where(put => put.name == name).Include(p => p.product).ThenInclude(b => b.names).ThenInclude(b => b.language).Include(b => b.product).ThenInclude(b => b.subgroup).ThenInclude(b => b.names).Select(s => new Tuple<int, Aliment>(1, (Aliment)s.product)).ToListAsync();
result.AddRange(await _context.Aliments.Include(b => b.names).Include(b => b.subgroup).ThenInclude(b => b.names).Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower())).Select(s => new Tuple<int, Aliment>(1, s)).ToListAsync());
result.AddRange(await _context.Aliments.Include(b => b.names).Include(b => b.subgroup).ThenInclude(b => b.names).Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()))).Select(s => new Tuple<int, Aliment>(2, s)).ToListAsync());
result.AddRange(await _context.Aliments.Include(b => b.names).Include(b => b.subgroup).ThenInclude(b => b.names).Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()))).Select(s => new Tuple<int, Aliment>(3, s)).ToListAsync());
return _mapper.Map<List<Aliment>, List<AlimentDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Distinct().ToList(), opts: opt => opt.Items["language"] = languageFR).ToList();
}
public async Task Create(AlimentDto alimentDto)
{
var languageFR = await getLanguageFR();
if (await _context.Aliments.AnyAsync(x => alimentDto.ciqual_code.Equals(x.ciqual)))
throw new Exception(alimentDto.ciqual_code + " already exists");
var aliment = _mapper.Map<Aliment>(alimentDto, opts: opt => opt.Items["language"] = languageFR);
var subgroup = await _context.ProductSubGroups.FirstOrDefaultAsync(g => g.names.Any(gn => gn.name.Equals(alimentDto.groupe)));
if (subgroup == null) {
subgroup = await CreateSubGroup(alimentDto);
await _context.ProductSubGroups.AddAsync(subgroup, default);
}
aliment.names.Add(new ProductLanguage() { id = new Guid(), name = alimentDto.nom_francais, language = languageFR });
aliment.subgroup = subgroup;
await _context.Aliments.AddAsync(aliment, default);
await _context.SaveChangesAsync();
}
public async Task Update(AlimentDto alimentDto)
{
var languageFR = await getLanguageFR();
var aliment = await this._context.Aliments.FirstOrDefaultAsync(al => al.ciqual == alimentDto.ciqual_code);
if (aliment == new Aliment() || aliment == null)
throw new Exception("Aliment does not exist");
var subgroup = await _context.ProductSubGroups.FirstOrDefaultAsync(g => g.names.Any(gn => gn.name.Equals(alimentDto.groupe)));
if (subgroup == null) {
subgroup = await CreateSubGroup(alimentDto);
await _context.ProductSubGroups.AddAsync(subgroup, default);
}
aliment.subgroup = subgroup;
var names = aliment.names.FirstOrDefault(aln => aln.language.ISOCode == languageFR.ISOCode);
if (names == null)
aliment.names.Add(new ProductLanguage() { id = new Guid(), language = languageFR, name = alimentDto.nom_francais });
else
names.name = alimentDto.nom_francais;
_mapper.Map(alimentDto, aliment, opts: opt => opt.Items["language"] = languageFR);
_context.Aliments.Update(aliment);
await _context.SaveChangesAsync();
}
private async Task<ProductSubGroup> CreateSubGroup(AlimentDto alimentDto) {
var languageFR = await getLanguageFR();
ProductGroup group = await _context.ProductGroups.FirstAsync(pg => pg.names.Any(pgn => pgn.name.Equals("Aliment") && pgn.language == languageFR));
return new ProductSubGroup() {
id = new Guid(),
names = new List<ProductSubGroupLanguage>() {
new ProductSubGroupLanguage() {
id = new Guid(),
language = languageFR,
name = alimentDto.groupe
}
},
Groupe = group
};
}
private async Task<Language> getLanguageFR() {
return await _context.Languages.FirstAsync(l => l.ISOCode == "FR");
}
}
}

View File

@ -0,0 +1,116 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface ICurrencyRepository
{
Task<List<CurrencyDto>> GetAllCurrencies();
Task<CurrencyDto?> GetCurrency(Guid id);
Task<CurrencyDto?> GetCurrencyByISO(string isoCode);
Task<List<CurrencyDto>> GetCurrencies(string name, string languageCode);
Task Create(CurrencyDto CurrencyDto);
Task Update(Guid id, CurrencyDto CurrencyDto);
}
public class Currencieservice : ICurrencyRepository
{
private readonly ILogger<Currencieservice> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public Currencieservice(ILogger<Currencieservice> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<CurrencyDto>> GetAllCurrencies()
{
var allCurrencies = await GetCurrenciesWithInclude().ToListAsync();
return _mapper.Map<List<Currency>, List<CurrencyDto>>(allCurrencies);
}
public async Task<CurrencyDto?> GetCurrency(Guid id)
{
Currency? Currency = await GetCurrenciesWithInclude().FirstOrDefaultAsync(gr => gr.id == id);
if (Currency == null)
throw new Exception(string.Concat("Currency does not exist"));
return _mapper.Map<Currency, CurrencyDto>(Currency);
}
public async Task<CurrencyDto?> GetCurrencyByISO(string isoCode)
{
Currency? Currency = await GetCurrenciesWithInclude().FirstOrDefaultAsync(gr => gr.ISOCode == isoCode);
if (Currency == null)
throw new Exception(string.Concat("Currency does not exist"));
return _mapper.Map<Currency, CurrencyDto>(Currency);
}
public async Task<List<CurrencyDto>> GetCurrencies(string name, string languageCode)
{
var result = await GetCurrenciesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower() && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, Currency>(1, s)).ToListAsync();
result.AddRange(await GetCurrenciesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()) && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, Currency>(2, s)).ToListAsync());
result.AddRange(await GetCurrenciesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()) && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, Currency>(3, s)).ToListAsync());
return _mapper.Map<List<CurrencyDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Distinct().ToList()).ToList();
}
public async Task Create(CurrencyDto currencyDto)
{
var Currency = _mapper.Map<Currency>(currencyDto, opts: opt => opt.Items["language"] = currencyDto.language);
if (_context.Currencies.Any(c => c.ISOCode == currencyDto.ISOCode))
throw new Exception(string.Concat("Currency already exists"));
Currency.names = await GetNames(currencyDto, Currency);
foreach (CurrencyLanguage CurrencyLanguage in Currency.names) {
if (await _context.CurrencyLanguages.Include(b => b.language).AnyAsync(pgl => pgl.language.ISOCode.ToLower() == CurrencyLanguage.language.ISOCode.ToLower() && pgl.name.ToLower() == CurrencyLanguage.name.ToLower()))
throw new Exception(string.Concat("Currency already exists"));
}
await _context.Currencies.AddAsync(Currency, default);
await _context.SaveChangesAsync();
}
public async Task Update(Guid id, CurrencyDto currencyDto)
{
var Currency = await this._context.Currencies.FirstOrDefaultAsync(al => al.id == id);
if (Currency == new Currency() || Currency == null)
throw new Exception("Currency does not exist");
_mapper.Map(currencyDto, Currency, opts: opt => opt.Items["language"] = currencyDto.language);
Currency.names = await GetNames(currencyDto, Currency);
_context.Currencies.Update(Currency);
await _context.SaveChangesAsync();
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.Currency, GiecChallenge.Models.Language> GetCurrenciesWithInclude() {
return this._context.Currencies.Include(b => b.names).ThenInclude(b => b.language);
}
private async Task<List<CurrencyLanguage>> GetNames(CurrencyDto currencyDto, Currency Currency) {
var CurrencyLanguages = new List<CurrencyLanguage>();
foreach (CurrencyNamesDto name in currencyDto.names) {
var currentLanguageToInsert = await _context.Languages.FirstOrDefaultAsync(l => l.ISOCode.ToLower() == name.language.ToLower());
if (currentLanguageToInsert == null)
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
if (Currency.names.Any(l => l.language.ISOCode.ToLower() == name.language.ToLower()))
Currency.names.First(l => l.language.ISOCode.ToLower() == name.language.ToLower()).name = name.name;
else
Currency.names.Add(_mapper.Map<CurrencyLanguage>(name, opts: opt => {
opt.Items["language"] = currentLanguageToInsert;
}));
}
return Currency.names;
}
}
}

View File

@ -0,0 +1,106 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface IGroupRepository
{
Task<List<GroupDto>> GetAllGroups();
Task<GroupDto?> GetGroup(Guid id);
Task<List<GroupDto>> GetGroups(string name, string languageCode);
Task Create(GroupDto GroupDto);
Task Update(Guid id, GroupDto GroupDto);
}
public class GroupService : IGroupRepository
{
private readonly ILogger<GroupService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public GroupService(ILogger<GroupService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<GroupDto>> GetAllGroups()
{
var allGroups = await GetGroupsWithInclude().ToListAsync();
return _mapper.Map<List<ProductGroup>, List<GroupDto>>(allGroups);
}
public async Task<GroupDto?> GetGroup(Guid id)
{
ProductGroup? group = await GetGroupsWithInclude().FirstOrDefaultAsync(gr => gr.id == id);
if (group == null)
throw new Exception(string.Concat("Group does not exist"));
return _mapper.Map<ProductGroup, GroupDto>(group);
}
public async Task<List<GroupDto>> GetGroups(string name, string languageCode)
{
var result = await GetGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower() && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, ProductGroup>(1, s)).ToListAsync();
result.AddRange(await GetGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()) && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, ProductGroup>(2, s)).ToListAsync());
result.AddRange(await GetGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()) && aln.language.ISOCode == languageCode)).Select(s => new Tuple<int, ProductGroup>(3, s)).ToListAsync());
return _mapper.Map<List<GroupDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Distinct().ToList()).ToList();
}
public async Task Create(GroupDto groupDto)
{
var group = _mapper.Map<ProductGroup>(groupDto, opts: opt => opt.Items["language"] = groupDto.language);
group.names = await GetNames(groupDto, group);
foreach (ProductGroupLanguage groupLanguage in group.names) {
if (await _context.ProductGroupLanguages.Include(b => b.language).AnyAsync(pgl => pgl.language.ISOCode.ToLower() == groupLanguage.language.ISOCode.ToLower() && pgl.name.ToLower() == groupLanguage.name.ToLower()))
throw new Exception(string.Concat("Group already exists"));
}
await _context.ProductGroups.AddAsync(group, default);
await _context.SaveChangesAsync();
}
public async Task Update(Guid id, GroupDto groupDto)
{
var group = await this._context.ProductGroups.FirstOrDefaultAsync(al => al.id == id);
if (group == new ProductGroup() || group == null)
throw new Exception("Group does not exist");
_mapper.Map(groupDto, group, opts: opt => opt.Items["language"] = groupDto.language);
group.names = await GetNames(groupDto, group);
_context.ProductGroups.Update(group);
await _context.SaveChangesAsync();
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.ProductGroup, GiecChallenge.Models.Language> GetGroupsWithInclude() {
return this._context.ProductGroups.Include(b => b.names).ThenInclude(b => b.language);
}
private async Task<List<ProductGroupLanguage>> GetNames(GroupDto groupDto, ProductGroup group) {
var groupLanguages = new List<ProductGroupLanguage>();
foreach (GroupNamesDto name in groupDto.names) {
if (!Guid.TryParse(name.language, out Guid languageId))
throw new Exception(string.Concat(name.language, " is not valid"));
var currentLanguageToInsert = await _context.Languages.FirstOrDefaultAsync(l => l.id == languageId);
if (currentLanguageToInsert == null)
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
if (group.names.Any(l => l.id == languageId))
group.names.First(l => l.language.id == languageId).name = name.name;
else
group.names.Add(_mapper.Map<ProductGroupLanguage>(name, opts: opt => {
opt.Items["language"] = currentLanguageToInsert;
}));
}
return group.names;
}
}
}

View File

@ -0,0 +1,103 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface ILanguageRepository
{
Task<List<LanguageDto>> GetAllLanguages();
Task<LanguageDto?> GetLanguage(Guid id);
Task<List<LanguageDto>> GetLanguages(string name, string languageCode);
Task Create(LanguageDto LanguageDto);
Task Update(Guid id, LanguageDto LanguageDto);
}
public class LanguageService : ILanguageRepository
{
private readonly ILogger<LanguageService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public LanguageService(ILogger<LanguageService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<LanguageDto>> GetAllLanguages()
{
var allLanguages = await GetLanguagesWithInclude().ToListAsync();
return _mapper.Map<List<Language>, List<LanguageDto>>(allLanguages);
}
public async Task<LanguageDto?> GetLanguage(Guid id)
{
Language? Language = await GetLanguagesWithInclude().FirstOrDefaultAsync(gr => gr.id == id);
if (Language == null)
throw new Exception(string.Concat("Language does not exist"));
return _mapper.Map<Language, LanguageDto>(Language);
}
public async Task<List<LanguageDto>> GetLanguages(string name, string languageCode)
{
var result = await GetLanguagesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower())).Select(s => new Tuple<int, Language>(1, s)).ToListAsync();
result.AddRange(await GetLanguagesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()))).Select(s => new Tuple<int, Language>(2, s)).ToListAsync());
result.AddRange(await GetLanguagesWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()))).Select(s => new Tuple<int, Language>(3, s)).ToListAsync());
return _mapper.Map<List<LanguageDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Distinct().ToList()).ToList();
}
public async Task Create(LanguageDto languageDto)
{
var language = _mapper.Map<Language>(languageDto, opts: opt => opt.Items["language"] = languageDto.language);
language.names = await GetNames(languageDto, language);
foreach (LanguageLanguage languageLanguage in language.names) {
if (await _context.LanguageLanguages.Include(b => b.language).AnyAsync(pgl => pgl.language.ISOCode.ToLower() == languageLanguage.language.ISOCode.ToLower() && pgl.name.ToLower() == languageLanguage.name.ToLower()))
throw new Exception(string.Concat("Language already exists"));
}
await _context.Languages.AddAsync(language);
await _context.SaveChangesAsync();
}
public async Task Update(Guid id, LanguageDto languageDto)
{
var language = await this._context.Languages.Include(b =>b.names).ThenInclude(b => b.language).FirstOrDefaultAsync(al => al.id == id);
if (language == new Language() || language == null)
throw new Exception("Language does not exist");
_mapper.Map(languageDto, language, opts: opt => opt.Items["language"] = languageDto.language);
language.names = await GetNames(languageDto, language);
_context.Languages.Update(language);
await _context.SaveChangesAsync();
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.Language, GiecChallenge.Models.Language> GetLanguagesWithInclude() {
return this._context.Languages.Include(b => b.names).ThenInclude(b => b.language);
}
private async Task<List<LanguageLanguage>> GetNames(LanguageDto languageDto, Language language) {
foreach (LanguageNamesDto name in languageDto.names) {
var currentLanguageToInsert = name.language == language.ISOCode ?
language :
await _context.Languages.Include(b => b.names).SingleOrDefaultAsync(l => l.ISOCode.ToLower() == name.language.ToLower());
if (currentLanguageToInsert == null)
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
if (language.names.Any(l => l.language.ISOCode.ToLower() == name.language.ToLower()))
language.names.First(l => l.language.ISOCode == name.language).name = name.name;
else
language.names.Add(_mapper.Map<LanguageLanguage>(name, opts: opt => {
opt.Items["language"] = currentLanguageToInsert;
}));
}
return language.names;
}
}
}

View File

@ -0,0 +1,190 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface IProductRepository
{
Task<List<ProductDto>> GetAllProducts();
Task<ProductDto?> GetProduct(Guid id);
Task<List<ProductDto>> GetProducts(string name, string languageCode);
Task<List<ProductDto>> GetProductsByGroup(string groupId);
Task<List<ProductDto>> GetProductsBySubGroup(string subGroupId);
Task Create(ProductDto ProductDto);
Task Update(Guid id, ProductDto ProductDto);
Task CreateTranslation(ProductUserTranslationDTO translationDTO);
Task UpdateTranslation(ProductUserTranslationDTO translationDTO, Guid userId);
Task DeleteTranslation(ProductUserTranslationDTO translationDTO, Guid userId);
}
public class ProductService : IProductRepository
{
private readonly ILogger<ProductService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public ProductService(ILogger<ProductService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<ProductDto>> GetAllProducts()
{
var allProducts = await GetProductsWithInclude().ToListAsync();
return _mapper.Map<List<Product>, List<ProductDto>>(allProducts);
}
public async Task<ProductDto?> GetProduct(Guid id)
{
Product? product = await GetProductsWithInclude().FirstOrDefaultAsync(gr => gr.id == id);
if (product == null)
throw new Exception(string.Concat("Product does not exist"));
return _mapper.Map<Product, ProductDto>(product);
}
public async Task<List<ProductDto>> GetProductsByGroup(string groupId)
{
if (!Guid.TryParse(groupId, out Guid group)) {
throw new Exception(string.Concat("Group ", groupId, " doesn't exist"));
}
var result = await _context.Products.Include(b => b.subgroup).ThenInclude(b => b.Groupe).Where(p => p.subgroup.Groupe.id == group).ToListAsync();
return _mapper.Map<List<ProductDto>>(result).ToList();
}
public async Task<List<ProductDto>> GetProductsBySubGroup(string subGroupId)
{
if (!Guid.TryParse(subGroupId, out Guid subGroup)) {
throw new Exception(string.Concat("Sub group ", subGroupId, " doesn't exist"));
}
var result = await _context.Products.Include(b => b.subgroup).Where(p => p.subgroup.id == subGroup).ToListAsync();
return _mapper.Map<List<ProductDto>>(result).ToList();
}
public async Task<List<ProductDto>> GetProducts(string name, string languageCode)
{
var result = await _context.ProductUserTranslations.Where(put => put.name.ToLower() == name.ToLower()).Include(put => put.product).ThenInclude(b => b.names).ThenInclude(b => b.language).Include(put => put.product).ThenInclude(b => b.subgroup).ThenInclude(b => b.names).Include(put => put.product).ThenInclude(b => b.subgroup).ThenInclude(b => b.Groupe).ThenInclude(b => b.names).Select(s => new Tuple<int, Product>(1, s.product)).Take(10).ToListAsync();
result.AddRange(await GetProductsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower() && aln.language.ISOCode == languageCode)).Take(10).Select(s => new Tuple<int, Product>(2, s)).ToListAsync());
result.AddRange(await GetProductsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()) && aln.language.ISOCode == languageCode)).Take(10).Select(s => new Tuple<int, Product>(3, s)).ToListAsync());
result.AddRange(await GetProductsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()) && aln.language.ISOCode == languageCode)).Take(10).Select(s => new Tuple<int, Product>(4, s)).ToListAsync());
return _mapper.Map<List<ProductDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Take(10).Distinct().ToList()).ToList();
}
public async Task Create(ProductDto productDto)
{
var product = _mapper.Map<Product>(productDto, opts: opt => opt.Items["language"] = productDto.language);
product.names = await GetNames(productDto, product);
product.subgroup = await getSubGroup(productDto);
foreach (ProductLanguage productLanguage in product.names) {
if (await GetProductsWithInclude().AnyAsync(p =>
p.names.Any(pn => pn.name.ToLower() == productLanguage.name.ToLower() && pn.language.id == productLanguage.language.id) &&
p.subgroup.id == product.subgroup.id
))
throw new Exception(string.Concat("Product already exists"));
}
await _context.Products.AddAsync(product, default);
await _context.SaveChangesAsync();
}
public async Task Update(Guid id, ProductDto productDto)
{
var product = await this._context.Products.FirstOrDefaultAsync(al => al.id == id);
if (product == new Product() || product == null)
throw new Exception("Product does not exist");
_mapper.Map(productDto, product, opts: opt => opt.Items["language"] = productDto.language);
product.names = await GetNames(productDto, product);
product.subgroup = await getSubGroup(productDto);
_context.Products.Update(product);
await _context.SaveChangesAsync();
}
public async Task CreateTranslation(ProductUserTranslationDTO translationDTO) {
var translation = _mapper.Map<ProductUserTranslation>(translationDTO);
var user = await _context.Users.FirstOrDefaultAsync(l => l.id.ToString() == translationDTO.user);
if (user == null)
throw new Exception(string.Concat("User does not exist"));
var product = await _context.Products.FirstOrDefaultAsync(p => p.id.ToString() == translationDTO.product);
if (product == null)
throw new Exception(string.Concat("Product does not exist"));
translation.user = user;
translation.product = product;
await _context.ProductUserTranslations.AddAsync(translation);
await _context.SaveChangesAsync();
}
public async Task UpdateTranslation(ProductUserTranslationDTO translationDTO, Guid userId) {
if (!Guid.TryParse(translationDTO.id, out Guid translationId))
throw new Exception(string.Concat("Translation does not exist"));
var translation = await this._context.ProductUserTranslations.FirstOrDefaultAsync(al => al.id == translationId && al.user.id == userId);
if (translation == new ProductUserTranslation() || translation == null)
throw new Exception("Translation doesn't exist");
translation.name = translationDTO.name;
_context.ProductUserTranslations.Update(translation);
await _context.SaveChangesAsync();
}
public async Task DeleteTranslation(ProductUserTranslationDTO translationDTO, Guid user) {
var translation = await _context.ProductUserTranslations.FirstOrDefaultAsync(p => p.id.ToString() == translationDTO.id && p.user.id == user);
if (translation == null)
throw new Exception(string.Concat("Translation does not exist"));
_context.ProductUserTranslations.Remove(translation);
await _context.SaveChangesAsync();
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.Product, GiecChallenge.Models.Language> GetProductsWithInclude() {
return this._context.Products.Include(b => b.names).ThenInclude(b => b.language).Include(b => b.subgroup).ThenInclude(b => b.names).ThenInclude(b => b.language).Include(b => b.subgroup).ThenInclude(b => b.Groupe).ThenInclude(b => b.names).ThenInclude(b => b.language);
}
private async Task<List<ProductLanguage>> GetNames(ProductDto productDto, Product product) {
var productLanguages = new List<ProductLanguage>();
foreach (ProductNamesDto name in productDto.names) {
if (!Guid.TryParse(name.language, out Guid languageId)) {
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
}
var currentLanguageToInsert = await _context.Languages.SingleOrDefaultAsync(l => l.id == languageId);
if (currentLanguageToInsert == null)
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
if (product.names.Any(l => l.language.ISOCode.ToLower() == name.language.ToLower()))
product.names.First(l => l.language.ISOCode.ToLower() == name.language.ToLower()).name = name.name;
else
product.names.Add(_mapper.Map<ProductLanguage>(name, opts: opt => {
opt.Items["language"] = currentLanguageToInsert;
}));
}
return product.names;
}
private async Task<ProductSubGroup> getSubGroup(ProductDto product) {
if (!Guid.TryParse(product.group, out Guid groupId))
throw new Exception(string.Concat("Group does not exist"));
var subGroup = await this._context.ProductSubGroups.FirstOrDefaultAsync(pg => pg.id == groupId);
if (subGroup == null)
throw new Exception(string.Concat("Group does not exist"));
return subGroup;
}
}
}

View File

@ -0,0 +1,403 @@
using System.Data;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
namespace GiecChallenge.Services
{
public interface IPurchaseRepository
{
Task<List<PurchaseDto>> GetAll(Guid userId);
Task<PurchaseDto> Get(Guid userId, Guid purchaseId);
Task<List<PurchaseDto>> GetBetweenDate(Guid userId, DateTime dateBegin, DateTime dateEnd);
Task<double> GetCO2BetweenDate(Guid userId, DateTime dateBegin, DateTime dateEnd);
Task Create(Guid userId, PurchaseDto purchaseDto);
Task Update(Guid userId, PurchaseDto purchaseDto);
Task Delete(Guid userId, Guid purchaseId);
Task DeleteLine(Guid userId, Guid purchaseLineId);
Task<PurchaseLaRucheImportReturnDto> ImportLaRuchePurchase(Guid userId, PurchaseLaRucheDto purchaseLaRuche);
}
public class PurchaseService : IPurchaseRepository
{
private readonly ILogger<PurchaseService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public PurchaseService(ILogger<PurchaseService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<PurchaseDto>> GetAll(Guid userId)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
var purchases = await GetPurchasesWithInclude().Where(p => p.user.id == userId).ToListAsync();
return getDtos(purchases, user);
}
public async Task<PurchaseDto> Get(Guid userId, Guid purchaseId)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
var purchase = await GetPurchasesWithInclude().FirstOrDefaultAsync(p => p.user.id == userId && p.id == purchaseId);
if (purchase == null) {
throw new Exception("Purchase does not exist");
}
return getDto(purchase, user);
}
public async Task<List<PurchaseDto>> GetBetweenDate(Guid userId, DateTime dateBegin, DateTime dateEnd)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
var purchases = await _context.Purchases.Include(b => b.products).ThenInclude(b => b.product).Where(p => p.user.id == userId && p.datePurchase >= dateBegin && p.datePurchase <= dateEnd).ToListAsync();
return getDtos(purchases, user);
}
public async Task<double> GetCO2BetweenDate(Guid userId, DateTime dateBegin, DateTime dateEnd)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
var purchases = await _context.Purchases.Include(b => b.products).ThenInclude(b => b.product).Where(p => p.user.id == userId && p.datePurchase >= dateBegin && p.datePurchase <= dateEnd).ToListAsync();
double CO2Emissions = purchases.Sum(p => p.products.Sum(pro => pro.product.CO2 * pro.quantity));
return CO2Emissions;
}
public async Task Create(Guid userId, PurchaseDto purchaseDto)
{
Purchase purchase = _mapper.Map<Purchase>(purchaseDto);
purchase = await getPurchaseFromDto(userId, purchase, purchaseDto);
purchase.id = Guid.NewGuid();
foreach (ProductPurchase products in purchase.products) {
_context.ProductPurchases.Add(products);
}
await _context.Purchases.AddAsync(purchase);
await _context.SaveChangesAsync();
}
public async Task Delete(Guid userId, Guid purchaseID)
{
Purchase? purchase = await _context.Purchases.FirstOrDefaultAsync(p => p.id == purchaseID && p.user.id == userId);
if (purchase == null) {
throw new Exception("Purchase does not exist");
}
_context.Purchases.Remove(purchase);
await _context.SaveChangesAsync();
}
public async Task DeleteLine(Guid userId, Guid purchaseLineID)
{
ProductPurchase? productPurchase = await _context.ProductPurchases.FirstOrDefaultAsync(p => p.id == purchaseLineID && p.purchase.user.id == userId);
if (productPurchase == null) {
throw new Exception("Product purchase does not exist");
}
_context.ProductPurchases.Remove(productPurchase);
if (!productPurchase.purchase.products.Any())
_context.Purchases.Remove(productPurchase.purchase);
await _context.SaveChangesAsync();
}
public async Task Update(Guid userId, PurchaseDto purchaseDto)
{
Purchase? purchase = await _context.Purchases.Include(p => p.products).FirstOrDefaultAsync(p => p.id == purchaseDto.id);
if (purchase == null) {
throw new Exception("Purchase does not exist");
}
purchase = await getPurchaseFromDto(userId, purchase, purchaseDto);
_context.Purchases.Update(purchase);
foreach (ProductPurchase products in purchase.products) {
_context.ProductPurchases.Add(products);
}
await _context.SaveChangesAsync();
}
public async Task<PurchaseLaRucheImportReturnDto> ImportLaRuchePurchase(Guid userId, PurchaseLaRucheDto purchaseLaRuche)
{
List<ProductPurchaseDto> productToRetrieve = new List<ProductPurchaseDto>();
Purchase purchase = new Purchase();
purchase.datePurchase = purchaseLaRuche.datePurchase;
purchase.user = await GetUserInLaRocheImport(purchaseLaRuche, userId);
Currency currency = await _context.Currencies.FirstAsync(c => c.ISOCode == "EUR");
foreach (string productLine in purchaseLaRuche.command.Split(new[] { "\n \n\n"}, StringSplitOptions.None)) {
string[] productCaracteristics = productLine.Trim().Split("\n");
ProductPurchase productPurchase = await GetProductPurchaseFromLine(productCaracteristics, currency);
if (productPurchase.product == null) {
ProductPurchaseDto purchaseDto = _mapper.Map<ProductPurchaseDto>(productPurchase);
purchaseDto.product = productCaracteristics[0];
productToRetrieve.Add(purchaseDto);
}
else if (purchase.products.Any(pp => pp.product.id == productPurchase.id)) {
ProductPurchase alreadyInImport = purchase.products.First(pp => pp.product.id == productPurchase.id);
alreadyInImport.price += productPurchase.price;
alreadyInImport.quantity += productPurchase.quantity;
}
else
purchase.products.Add(productPurchase);
}
purchase.id = Guid.NewGuid();
await _context.Purchases.AddAsync(purchase);
foreach (ProductPurchase products in purchase.products) {
_context.ProductPurchases.Add(products);
}
await _context.SaveChangesAsync();
return new PurchaseLaRucheImportReturnDto() {
id = purchase.id,
productsToTranslate = productToRetrieve
};
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.Purchase, GiecChallenge.Models.Currency> GetPurchasesWithInclude() {
return this._context.Purchases.Include(b => b.products).ThenInclude(b => b.product).ThenInclude(b => b.names).ThenInclude(b => b.language)
.Include(b => b.user)
.Include(b => b.products).ThenInclude(b => b.currency);
}
private async Task<Purchase> getPurchaseFromDto(Guid userId, Purchase purchase, PurchaseDto purchaseDto) {
purchase.user = await GetPurchaseUserFromDto(userId, purchase, purchaseDto);
purchase.products = new List<ProductPurchase>();
_context.CarbonLoans.RemoveRange(await _context.CarbonLoans.Where(cl => cl.productPurchase.purchase == purchase).ToListAsync());
_context.Purchases.RemoveRange(await _context.Purchases.Where(cl => cl.initialPurchase == purchase).ToListAsync());
foreach (ProductPurchaseDto purchaseProductDto in purchaseDto.products) {
ProductPurchase purchaseProduct = await GetProductPurchaseFromDto(purchaseProductDto, purchase);
if (!string.IsNullOrEmpty(purchaseProductDto.translation) &&
!_context.ProductUserTranslations.Any(put => put.product == purchaseProduct.product && put.name == purchaseProductDto.translation)) {
_context.ProductUserTranslations.Add(new ProductUserTranslation() {
id = new Guid(),
user = purchase.user,
product = purchaseProduct.product,
name = purchaseProductDto.translation
});
}
if (!purchase.products.Any(p => p.product == purchaseProduct.product)) {
purchaseProduct.purchase = purchase;
if (purchaseProduct.id == Guid.Empty) {
purchaseProduct.id = Guid.NewGuid();
purchaseProduct.CO2Cost = purchaseProduct.product.CO2;
purchase.products.Add(purchaseProduct);
}
}
else {
purchaseProduct = purchase.products.First(p => p.product == purchaseProduct.product);
purchaseProduct.price += purchaseProductDto.price;
purchaseProduct.quantity += purchaseProductDto.quantity;
purchaseProduct.CO2Cost += purchaseProduct.product.CO2;
}
}
foreach (ProductPurchase productPurchase in purchase.products.Where(pp => pp.product.amortization > 0).ToList()) {
await addLoan(purchase, productPurchase);
}
return purchase;
}
private List<PurchaseDto> getDtos(List<Purchase> purchases, User user) {
List<PurchaseDto> allPurchases = new List<PurchaseDto>();
foreach (Purchase purchase in purchases) {
allPurchases.Add(getDto(purchase, user));
}
return allPurchases;
}
private PurchaseDto getDto(Purchase purchase, User user) {
var purchaseDto = _mapper.Map<PurchaseDto>(purchase);
foreach (ProductPurchase product in purchase.products) {
purchaseDto.products.Add(_mapper.Map<ProductPurchaseDto>(product, opts: opt => opt.Items["language"] = user.favoriteLanguage));
purchaseDto.CO2Cost += product.CO2Cost;
purchaseDto.WaterCost += product.product.water;
}
return purchaseDto;
}
private List<PurchaseDto> getPurchase(List<Purchase> purchases, User user) {
List<PurchaseDto> allPurchases = new List<PurchaseDto>();
foreach (Purchase purchase in purchases) {
var purchaseDto = _mapper.Map<PurchaseDto>(purchases, opts: opt => opt.Items["language"] = user.favoriteLanguage);
foreach (ProductPurchase product in purchase.products) {
purchaseDto.products.Add(_mapper.Map<ProductPurchaseDto>(product.product, opts: opt => opt.Items["language"] = user.favoriteLanguage));
}
allPurchases.Add(purchaseDto);
}
return allPurchases;
}
private async Task<User> GetUserInLaRocheImport(PurchaseLaRucheDto purchaseLaRuche, Guid userId) {
if (purchaseLaRuche.datePurchase > DateTime.Now) {
throw new Exception("Purchase date can't be in the future");
}
if (string.IsNullOrEmpty(purchaseLaRuche.command))
throw new Exception("No product selected");
User? user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
return user;
}
private async Task<ProductPurchase> GetProductPurchaseFromLine(string[] productCaracteristics, Currency currency) {
Product? product = await _context.Products.Include(b => b.names).Include(b => b.subgroup).ThenInclude(b => b.names).Where(al => al.names.Any(aln => aln.name.ToLower() == productCaracteristics[0].ToLower() && aln.language.ISOCode == "FR")).FirstOrDefaultAsync();
double quantity = 0;
double price = 0;
if (product == null) {
product = await _context.ProductUserTranslations.Where(put => put.name.ToLower() == productCaracteristics[0].ToLower()).Include(put => put.product).ThenInclude(b => b.names).ThenInclude(b => b.language).Include(put => put.product).ThenInclude(b => b.subgroup).ThenInclude(b => b.names).Select(s => s.product).FirstOrDefaultAsync();
}
try {
quantity = GetProductQuantity(
String.Join("", Regex.Matches(productCaracteristics[1].Replace("(", "").Replace(")", ""), @"([0-9]{0,4}\.?[0-9]{0,2}\s?×?)").Select(m => m.Value).ToList()).Replace("×", "*"),
Regex.Matches(productCaracteristics[1], @"([a-zA-Z]*)").Where(m => !string.IsNullOrEmpty(m.Value)).Select(m => m.Value).FirstOrDefault());
}
catch {
throw new Exception(string.Concat("Product quantity for ", productCaracteristics[0], " not correct"));
}
try {
price = double.Parse(productCaracteristics[2].Replace("€", "").Trim(), CultureInfo.InvariantCulture);
}
catch {
throw new Exception(string.Concat("Product price for ", productCaracteristics[0], " not correct"));
}
return new ProductPurchase() {
id = Guid.NewGuid(),
product = product,
currency = currency,
price = price,
quantity = quantity,
CO2Cost = product != null ? product.CO2 / (product.amortization + 1) : 0
};
}
private async Task addLoan(Purchase purchase, ProductPurchase productPurchase) {
CarbonLoan loan = new CarbonLoan();
loan.id = Guid.NewGuid();
loan.user = purchase.user;
loan.productPurchase = productPurchase;
loan.dateBegin = purchase.datePurchase;
loan.dateEnd = purchase.datePurchase.AddMonths(productPurchase.product.amortization);
await _context.CarbonLoans.AddAsync(loan);
int i = 1;
while (i < productPurchase.product.amortization) {
Purchase newPurchase = new Purchase() {
id = Guid.NewGuid(),
user = purchase.user,
datePurchase = purchase.datePurchase.AddMonths(i),
initialPurchase = purchase
};
ProductPurchase newProductPurchase = new ProductPurchase() {
id = Guid.NewGuid(),
product = productPurchase.product,
currency = productPurchase.currency,
purchase = newPurchase,
price = 0,
quantity = productPurchase.quantity,
CO2Cost = productPurchase.product.CO2 / (productPurchase.product.amortization + 1)
};
newPurchase.products.Add(newProductPurchase);
await _context.Purchases.AddAsync(newPurchase);
await _context.ProductPurchases.AddAsync(newProductPurchase);
i++;
}
}
private async Task<ProductPurchase> GetProductPurchaseFromDto(ProductPurchaseDto purchaseProductDto, Purchase purchase) {
ProductPurchase purchaseProduct = _mapper.Map<ProductPurchase>(purchaseProductDto);
if (Guid.TryParse(purchaseProductDto.id, out Guid purchaseId) && purchase.products.Any(p => p.id == purchaseId))
purchaseProduct.id = purchaseId;
if (purchaseProductDto.price < 0)
throw new Exception("Price must be superior than 0");
if (!Guid.TryParse(purchaseProductDto.product, out Guid productId))
throw new Exception("Product does not exist");
var product = await _context.Products.FirstOrDefaultAsync(p => p.id == productId);
if (product == null)
throw new Exception("Product does not exist");
purchaseProduct.product = product;
Currency? currency = null;
if (Guid.TryParse(purchaseProductDto.currencyIsoCode, out Guid currencyId))
currency = await _context.Currencies.FirstOrDefaultAsync(p => p.id == currencyId);
else
currency = await _context.Currencies.FirstOrDefaultAsync(p => p.ISOCode == purchaseProductDto.currencyIsoCode);
if (currency == null)
throw new Exception("Currency does not exist");
purchaseProduct.currency = currency;
return purchaseProduct;
}
private async Task<User> GetPurchaseUserFromDto(Guid userId, Purchase purchase, PurchaseDto purchaseDto) {
if (purchase.user.id == Guid.Empty) {
User? user = await _context.Users.FirstOrDefaultAsync(u => u.id == userId);
if (user == null)
throw new Exception("Nice try");
purchase.user = user;
if (!purchaseDto.products.Any()) {
throw new Exception("No product selected");
}
}
else if (purchase.user.id != userId) {
throw new Exception("Purchase does not exist");
}
if (!purchaseDto.products.Any())
throw new Exception("No product selected");
return purchase.user;
}
private double GetProductQuantity(string quantityString, string unit) {
double finalQuantity = Convert.ToDouble(new DataTable().Compute(quantityString,null));
if (unit == "g" || unit == "cl")
finalQuantity = finalQuantity / 1000;
return finalQuantity;
}
}
}

View File

@ -0,0 +1,121 @@
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.EntityFrameworkCore;
namespace GiecChallenge.Services
{
public interface ISubGroupRepository
{
Task<List<SubGroupDto>> GetAllSubGroups();
Task<SubGroupDto?> GetSubGroup(Guid id);
Task<List<SubGroupDto>> GetSubGroups(string name, string languageCode);
Task Create(SubGroupDto SubGroupDto);
Task Update(Guid id, SubGroupDto SubGroupDto);
}
public class SubGroupService : ISubGroupRepository
{
private readonly ILogger<SubGroupService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
public SubGroupService(ILogger<SubGroupService> logger,
IMapper mapper,
GiecChallengeContext context) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
}
public async Task<List<SubGroupDto>> GetAllSubGroups()
{
var allSubGroups = await GetSubGroupsWithInclude().ToListAsync();
return _mapper.Map<List<ProductSubGroup>, List<SubGroupDto>>(allSubGroups);
}
public async Task<SubGroupDto?> GetSubGroup(Guid id)
{
ProductSubGroup? subgroup = await GetSubGroupsWithInclude().FirstOrDefaultAsync(gr => gr.id == id);
if (subgroup == null)
throw new Exception(string.Concat("Sub Group does not exist"));
return _mapper.Map<ProductSubGroup, SubGroupDto>(subgroup);
}
public async Task<List<SubGroupDto>> GetSubGroups(string name, string languageCode)
{
var result = await GetSubGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower() == name.ToLower())).Select(s => new Tuple<int, ProductSubGroup>(1, s)).ToListAsync();
result.AddRange(await GetSubGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().StartsWith(name.ToLower()))).Select(s => new Tuple<int, ProductSubGroup>(2, s)).ToListAsync());
result.AddRange(await GetSubGroupsWithInclude().Where(al => al.names.Any(aln => aln.name.ToLower().Contains(name.ToLower()))).Select(s => new Tuple<int, ProductSubGroup>(3, s)).ToListAsync());
return _mapper.Map<List<SubGroupDto>>(result.OrderBy(s => s.Item1).Select(s => s.Item2).Distinct().ToList()).ToList();
}
public async Task Create(SubGroupDto subGroupDto)
{
var subgroup = _mapper.Map<ProductSubGroup>(subGroupDto, opts: opt => opt.Items["language"] = subGroupDto.language);
if (!Guid.TryParse(subGroupDto.group, out Guid groupId))
throw new Exception(string.Concat(subGroupDto.group, " is not valid"));
foreach (SubGroupNamesDto names in subGroupDto.names) {
if (await _context.ProductSubGroups.Include(b => b.Groupe).ThenInclude(b => b.names).ThenInclude(b => b.language).AnyAsync(psg => psg.names.Any(psgn => psgn.name.ToLower() == names.name.ToLower() && psg.Groupe.id == groupId)))
throw new Exception(string.Concat("Sub Group already exists"));
}
subgroup.names = await GetNames(subGroupDto, subgroup);
subgroup.Groupe = await getGroup(subGroupDto, groupId);
await _context.ProductSubGroups.AddAsync(subgroup, default);
await _context.SaveChangesAsync();
}
public async Task Update(Guid id, SubGroupDto subGroupDto)
{
if (!Guid.TryParse(subGroupDto.group, out Guid groupId))
throw new Exception(string.Concat(subGroupDto.group, " is not valid"));
var subGroup = await this._context.ProductSubGroups.FirstOrDefaultAsync(al => al.id == id);
if (subGroup == new ProductSubGroup() || subGroup == null)
throw new Exception("Sub Group does not exist");
subGroup = _mapper.Map(subGroupDto, subGroup, opts: opt => opt.Items["language"] = subGroupDto.language);
subGroup.names = await GetNames(subGroupDto, subGroup);
if (!string.IsNullOrEmpty(subGroupDto.group))
subGroup.Groupe = await getGroup(subGroupDto, groupId);
_context.ProductSubGroups.Update(subGroup);
await _context.SaveChangesAsync();
}
private Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<GiecChallenge.Models.ProductSubGroup, GiecChallenge.Models.Language> GetSubGroupsWithInclude() {
return this._context.ProductSubGroups.Include(b => b.names).ThenInclude(b => b.language).Include(b => b.Groupe).ThenInclude(b => b.names).ThenInclude(b => b.language);
}
private async Task<List<ProductSubGroupLanguage>> GetNames(SubGroupDto SubGroupDto, ProductSubGroup subGroup) {
foreach (SubGroupNamesDto name in SubGroupDto.names) {
if (!Guid.TryParse(name.language, out Guid languageId))
throw new Exception(string.Concat(name.language, " is not valid"));
var currentLanguageToInsert = await _context.Languages.FirstOrDefaultAsync(l => l.id == languageId);
if (currentLanguageToInsert == null)
throw new Exception(string.Concat("Language ", name.language, " doesn't exist"));
if (subGroup.names.Any(l => l.language.ISOCode.ToLower() == name.language.ToLower()))
subGroup.names.First(l => l.language.ISOCode.ToLower() == name.language.ToLower()).name = name.name;
else
subGroup.names.Add(_mapper.Map<ProductSubGroupLanguage>(name, opts: opt => {
opt.Items["language"] = currentLanguageToInsert;
}));
}
return subGroup.names;
}
private async Task<ProductGroup> getGroup(SubGroupDto subGroupDto, Guid groupId) {
var group = await this._context.ProductGroups.FirstOrDefaultAsync(pg => pg.id == groupId);
if (group == null)
throw new Exception(string.Concat("Group does not exist"));
return group;
}
}
}

View File

@ -0,0 +1,147 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using AutoMapper;
using GiecChallenge.Models;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
namespace GiecChallenge.Services
{
public interface IUserRepository
{
Task<object> Login(UserDto userDto);
Task Register(UserDto userDto);
}
public class UserService : IUserRepository
{
private readonly ILogger<UserService> _logger;
private readonly IMapper _mapper;
private readonly GiecChallengeContext _context;
private readonly IConfiguration _configuration;
public UserService(ILogger<UserService> logger,
IMapper mapper,
GiecChallengeContext context,
IConfiguration configuration) {
this._logger = logger;
this._mapper = mapper;
this._context = context;
this._configuration = configuration;
}
public async Task<object> Login(UserDto userDto)
{
var user = await _context.Users.Include(u => u.groups).ThenInclude(g => g.userGroup).FirstOrDefaultAsync(u => u.email == userDto.email);
if (user != null && String.Compare(EncryptPassword(userDto.password, user.hash).hash, user.password) == 0)
{
var userRoles = user.groups;
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole.userGroup.name));
}
var token = GetToken(authClaims);
return new {
token = new JwtSecurityTokenHandler().WriteToken(token),
validTo = token.ValidTo
};
}
throw new Exception("Email or password is incorrect");
}
public async Task Register(UserDto userDto)
{
if (await this._context.Users.AnyAsync(u => u.email == userDto.email))
throw new Exception("User already exist");
var user = _mapper.Map<User>(userDto);
Language? favoriteLanguage = await _context.Languages.FirstOrDefaultAsync(l => l.ISOCode == userDto.language);
if (favoriteLanguage == null)
throw new Exception("Language does not exist");
user.favoriteLanguage = favoriteLanguage;
var group = await _context.UserGroups.FirstOrDefaultAsync(ug => ug.name == "Classic");
if (group == null)
throw new Exception("Group does not exist");
user.groups.Add(new UserInGroup() {
userGroup = group,
user = user
});
var hashSalt = EncryptPassword(userDto.password);
user.password = hashSalt.hash;
user.hash = hashSalt.salt;
await _context.Users.AddAsync(user);
await _context.SaveChangesAsync();
}
private HashSalt EncryptPassword(string password, byte[] salt = null!)
{
if (salt == null || salt.Length == 0) {
salt = new byte[128 / 8]; // Generate a 128-bit salt using a secure PRNG
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
salt = Concat(Encoding.ASCII.GetBytes(_configuration.GetValue<string>("PasswordHash")!), salt);
}
string encryptedPassw = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8
));
return new HashSalt { hash = encryptedPassw , salt = salt };
}
private JwtSecurityToken GetToken(List<Claim> authClaims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetValue<string>("JWT:Secret")!));
var token = new JwtSecurityToken(
issuer: _configuration.GetValue<string>("JWT:ValidIssuer")!,
audience: _configuration.GetValue<string>("JWT:ValidAudience")!,
expires: DateTime.Now.AddDays(5),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return token;
}
static byte[] Concat(byte[] a, byte[] b)
{
byte[] output = new byte[a.Length + b.Length];
for (int i = 0; i < a.Length; i++)
output[i] = a[i];
for (int j = 0; j < b.Length; j++)
output[a.Length+j] = b[j];
return output;
}
private class HashSalt
{
public string hash {get;set;} = string.Empty;
public byte[] salt {get;set;} = null!;
}
}
}

View File

@ -0,0 +1,19 @@
{
"ConnectionStrings": {
"PostgreSQL": "User ID=maxime;Password=S?$9<Sp5JTX4-aC4=8J*;Host=localhost;Port=15432;Database=GiecChallenge;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"OriginAllowed": "http://localhost:3000",
"PasswordHash" : "U^CbUUV,$MMU]2lD$MFZ5;Bui#)XTS",
"JWT": {
"ValidAudience": "http://localhost:7021",
"ValidIssuer": "http://localhost:7021",
"Secret": "eAD+PhDIZ2(d2/<|,yvA/8'Z;[Wl|Z"
}
}

View File

@ -0,0 +1,19 @@
{
"ConnectionStrings": {
"PostgreSQL": ""
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "",
"OriginAllowed": "",
"PasswordHash" : "",
"JWT": {
"ValidAudience": "",
"ValidIssuer": "",
"Secret": ""
}
}

View File

@ -0,0 +1,18 @@
{
"ConnectionStrings": {
"PostgreSQL": "User ID=maxime;Password=DQM{Z8vtk(KM9U?9AK(f;Host=giecchallenge_db;Port=14432;Database=GiecChallenge;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"PasswordHash" : "75@zO*#8u*b?P8aZz@cF",
"JWT": {
"ValidAudience": "http://localhost:7021",
"ValidIssuer": "http://localhost:7021",
"Secret": "8*4(IE@PT8{$4U$m+sZh"
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

69
docker-compose.yml Normal file
View File

@ -0,0 +1,69 @@
version: '3.4'
networks:
dev:
driver: bridge
services:
giecchallenge_backend:
image: ${REGISTRY:-giecchalleng-backend}/giecchallenge-backend.api:${PLATFORM:-linux}-${TAG:-latest}
depends_on:
- "giecchallenge_db"
container_name: giecchallenge-backend
ports:
- "17021:443"
- "17020:80"
build:
context: .
dockerfile: ./backend/GiecChallenge/Dockerfile
environment:
- ConnectionStrings__PostgreSQL=host=giecchallenge_db;User ID=maxime;Password=<POSTGREDB_PASSWORD>;Port=14432;Database=GiecChallenge;Pooling=true;
- JWT__ValidAudience=https://giecchallenge-backend.maximeboulay.com
- JWT__ValidIssuer=https://giecchallenge-backend.maximeboulay.com
- JWT__Secret=<JWT__Secret>
- PasswordHash=<HASH>
- AllowedHosts=*
- OriginAllowed=https://giecchallenge.maximeboulay.com
networks:
- dev
giecchallenge_frontend:
image: ${REGISTRY:-giecchalleng-frontend}/giecchallenge-frontend.api:${PLATFORM:-linux}-${TAG:-latest}
depends_on:
- "giecchallenge_backend"
stdin_open: true
tty: true
container_name: giecchallenge-frontend
ports:
- "13000:3000"
build:
context: .
dockerfile: ./frontend/Dockerfile
args:
REACT_APP_API_URL: https://giecchallenge-backend.maximeboulay.com
environment:
- API_URL
networks:
- dev
giecchallenge_db:
image: postgres:latest
container_name: giecchallenge_db
environment:
- POSTGRES_USER=maxime
- POSTGRES_PASSWORD=<POSTGREDB_PASSWORD>
- POSTGRES_DB=GiecChallenge
expose:
- "14432"
ports:
- "14432:14432"
command: -p 14432
restart: always
volumes:
- customer_data:/var/lib/postgresql/data/
- ./backend/GiecChallenge/Data/giecchallenge.sql :/docker-entrypoint-initdb.d/seed.sql
networks:
- dev
volumes:
customer_data:

6
frontend/.dockerignore Normal file
View File

@ -0,0 +1,6 @@
node_modules
build
.dockerignore
**/.git
**/.DS_Store
**/node_modules

View File

@ -0,0 +1 @@
REACT_APP_API_URL=https://localhost:7021

1
frontend/.env.docker Normal file
View File

@ -0,0 +1 @@
DANGEROUSLY_DISABLE_HOST_CHECK=true

23
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

23
frontend/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"type": "firefox",
"request": "launch",
"name": "Launch Firefox against localhost",
"url": "http://localhost:3000",
"breakOnLoad": true,
"webRoot": "${workspaceFolder}"
}
]
}

16
frontend/Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM node:14-alpine AS builder
ENV NODE_ENV production
# Add a work directory
WORKDIR /src-frontend
# Cache and Install dependencies
COPY ./frontend/package.json .
COPY ./frontend/package-lock.json .
ARG REACT_APP_API_URL
ENV REACT_APP_API_URL=$REACT_APP_API_URL
RUN npm install
# Copy app files
COPY ./frontend/ .
RUN mv ./public/locales/fr ./public/locales/FR
RUN mv ./public/locales/en ./public/locales/EN
# Build the app
CMD ["npm", "run", "docker"]

44
frontend/README.md Normal file
View File

@ -0,0 +1,44 @@
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app), using the [Redux](https://redux.js.org/) and [Redux Toolkit](https://redux-toolkit.js.org/) template.
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.<br />
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br />
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.<br />
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.<br />
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br />
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you cant go back!**
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).

17521
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

52
frontend/package.json Normal file
View File

@ -0,0 +1,52 @@
{
"name": "frontend",
"version": "0.1.1",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"axios": "^1.3.2",
"bootstrap": "5.2.3",
"env-cmd": "^10.1.0",
"http-proxy-middleware": "^2.0.6",
"i18next": "22.4.9",
"i18next-browser-languagedetector": "7.0.1",
"i18next-xhr-backend": "3.2.2",
"react": "^18.2.0",
"react-bootstrap": "2.7.0",
"react-datepicker": "4.10.0",
"react-dom": "^18.2.0",
"react-i18next": "12.1.5",
"react-icons": "^4.7.1",
"react-modal": "^3.16.1",
"react-redux": "^8.0.5",
"react-router-dom": "^6.8.1",
"react-scripts": "^5.0.1",
"react-select": "5.7.0",
"react-toastify": "^9.1.1"
},
"scripts": {
"start": "react-scripts start",
"docker": "env-cmd -f .env.docker react-scripts --max-http-header-size=2048 start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

BIN
frontend/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>GiecChallenge</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -0,0 +1,5 @@
{
"login" : "Login",
"register" : "Register",
"logout" : "Log out"
}

Some files were not shown because too many files have changed in this diff Show More