diff --git a/Config/SQLQuery_insert test values.sql b/Config/SQLQuery_insert test values.sql index c879625f33..7be811a87c 100644 --- a/Config/SQLQuery_insert test values.sql +++ b/Config/SQLQuery_insert test values.sql @@ -17,149 +17,149 @@ ALTER DATABASE DB_NAME COLLATE Ukrainian_100_CI_AS; --==================== USERS ================================ INSERT INTO [dbo].[AspNetUsers] - ([Id] - ,[CreatingTime] - ,[LastLogin] - ,[LastName] - ,[MiddleName] - ,[FirstName] - ,[Role] - ,[UserName] - ,[NormalizedUserName] - ,[Email] - ,[NormalizedEmail] - ,[EmailConfirmed] - ,[PasswordHash] - ,[SecurityStamp] - ,[ConcurrencyStamp] - ,[PhoneNumber] - ,[PhoneNumberConfirmed] - ,[TwoFactorEnabled] - ,[LockoutEnd] - ,[LockoutEnabled] - ,[AccessFailedCount] - ,[IsRegistered]) - VALUES - ('16575ce5-38e3-4ae7-b991-4508ed488369' --Id - ,'2021-06-04 10:06:32.9282504 +00:00' --[CreatingTime] - ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin - ,'Батькоперший' --last name - ,'Іванович' --middle name - ,'Іван' --first name - ,'parent' --role - ,'test1@test.com' - ,'TEST1@TEST.COM' - ,'test1@test.com' - ,'TEST1@TEST.COM' - ,0 --emeil confirmed - ,'AQAAAAEAACcQAAAAELVU2FZw3HwShwuAXJR/xKFl938KgGpwdRRegrC5UFgZ5gnXdV6mEfalZCAngmX5sQ==' --password hash - ,'5Z5EXGBVHXUYVKZOBCCG7QLPWI6NJ22O' - ,'81dfc15c-1f36-48f6-99fd-9d028096cdec' - ,'1234567890' --phone - ,0 --phone confirmed - ,0 - ,NULL - ,1 - ,0 - ,0) --is registered - - ,('7604a851-66db-4236-9271-1f037ffe3a81' --Id - ,'2021-06-04 10:24:40.8990089 +00:00' --[CreatingTime] - ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin - ,'Батькодругий' --last name - ,'Петрович' --middle name - ,'Петро' --first name - ,'parent' --role - ,'test2@test.com' - ,'TEST2@TEST.COM' - ,'test2@test.com' - ,'TEST2@TEST.COM' - ,0 --emeil confirmed - ,'AQAAAAEAACcQAAAAEE6AlX8whARS9uZwJ5AUZx8490dgEnfrv7Q1lBXFqJwZcSoN6Mnvadhg75HG3ooT/A==' --password hash - ,'PB7OZCNE7PMY4YDB3VE34U5K2TXWGTLP' - ,'83915185-5bbd-4047-9901-638de8bd3a27' - ,'4561237890' --phone - ,0 --phone confirmed - ,0 - ,NULL - ,1 - ,0 - ,0) --is registered - - ,('47802b21-2fb5-435e-9057-75c43d002cef' --Id - ,'2021-06-04 10:29:56.7988521 +00:00' --[CreatingTime] - ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin - ,'Провайдерперший' --last name - ,'Семенович' --middle name - ,'Семен' --first name - ,'provider' --role - ,'test3@test.com' - ,'TEST3@TEST.COM' - ,'test3@test.com' - ,'TEST3@TEST.COM' - ,0 --emeil confirmed - ,'AQAAAAEAACcQAAAAELY6XF2g82E4EWQJl6UFWlojctlsLegV4f6qoME2IwwdI5fGaOq/Y6L6t+oa1N9j4Q==' --password hash - ,'EC36E7KFYXF2YMCSOSD27UXQRFKPMDKK' - ,'789c5891-212c-4339-95a2-80f75a168231' - ,'7890123456' --phone - ,0 --phone confirmed - ,0 - ,NULL - ,1 - ,0 - ,0) --is registered - - ,('5bff5f95-1848-4c87-9846-a567aeb407ea' --Id - ,'2021-06-04 10:33:26.6295481 +00:00' --[CreatingTime] - ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin - ,'Провайдердругий' --last name - ,'Борисович' --middle name - ,'Борис' --first name - ,'provider' --role - ,'test4@test.com' - ,'TEST4@TEST.COM' - ,'test4@test.com' - ,'TEST4@TEST.COM' - ,0 --emeil confirmed - ,'AQAAAAEAACcQAAAAEOJFUEjnmnHWPonAOsg9K6tBuT8e1cUYbBejJbRJf3smSTzUzqphZyFGtB7i6vuT0g==' --password hash - ,'NQTDJHP23OUXWSVOUSBDSUVBASPLCHV3' - ,'b419d5b7-fe0f-40a8-869f-76b2826de58f' - ,'0123456789' --phone - ,0 --phone confirmed - ,0 - ,NULL - ,1 - ,0 - ,0) --is registered -GO +([Id] + ,[CreatingTime] + ,[LastLogin] + ,[LastName] + ,[MiddleName] + ,[FirstName] + ,[Role] + ,[UserName] + ,[NormalizedUserName] + ,[Email] + ,[NormalizedEmail] + ,[EmailConfirmed] + ,[PasswordHash] + ,[SecurityStamp] + ,[ConcurrencyStamp] + ,[PhoneNumber] + ,[PhoneNumberConfirmed] + ,[TwoFactorEnabled] + ,[LockoutEnd] + ,[LockoutEnabled] + ,[AccessFailedCount] + ,[IsRegistered]) +VALUES + ('16575ce5-38e3-4ae7-b991-4508ed488369' --Id + ,'2021-06-04 10:06:32.9282504 +00:00' --[CreatingTime] + ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin + ,'Батькоперший' --last name + ,'Іванович' --middle name + ,'Іван' --first name + ,'parent' --role + ,'test1@test.com' + ,'TEST1@TEST.COM' + ,'test1@test.com' + ,'TEST1@TEST.COM' + ,0 --emeil confirmed + ,'AQAAAAEAACcQAAAAELVU2FZw3HwShwuAXJR/xKFl938KgGpwdRRegrC5UFgZ5gnXdV6mEfalZCAngmX5sQ==' --password hash + ,'5Z5EXGBVHXUYVKZOBCCG7QLPWI6NJ22O' + ,'81dfc15c-1f36-48f6-99fd-9d028096cdec' + ,'1234567890' --phone + ,0 --phone confirmed + ,0 + ,NULL + ,1 + ,0 + ,0) --is registered + + ,('7604a851-66db-4236-9271-1f037ffe3a81' --Id + ,'2021-06-04 10:24:40.8990089 +00:00' --[CreatingTime] + ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin + ,'Батькодругий' --last name + ,'Петрович' --middle name + ,'Петро' --first name + ,'parent' --role + ,'test2@test.com' + ,'TEST2@TEST.COM' + ,'test2@test.com' + ,'TEST2@TEST.COM' + ,0 --emeil confirmed + ,'AQAAAAEAACcQAAAAEE6AlX8whARS9uZwJ5AUZx8490dgEnfrv7Q1lBXFqJwZcSoN6Mnvadhg75HG3ooT/A==' --password hash + ,'PB7OZCNE7PMY4YDB3VE34U5K2TXWGTLP' + ,'83915185-5bbd-4047-9901-638de8bd3a27' + ,'4561237890' --phone + ,0 --phone confirmed + ,0 + ,NULL + ,1 + ,0 + ,0) --is registered + + ,('47802b21-2fb5-435e-9057-75c43d002cef' --Id + ,'2021-06-04 10:29:56.7988521 +00:00' --[CreatingTime] + ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin + ,'Провайдерперший' --last name + ,'Семенович' --middle name + ,'Семен' --first name + ,'provider' --role + ,'test3@test.com' + ,'TEST3@TEST.COM' + ,'test3@test.com' + ,'TEST3@TEST.COM' + ,0 --emeil confirmed + ,'AQAAAAEAACcQAAAAELY6XF2g82E4EWQJl6UFWlojctlsLegV4f6qoME2IwwdI5fGaOq/Y6L6t+oa1N9j4Q==' --password hash + ,'EC36E7KFYXF2YMCSOSD27UXQRFKPMDKK' + ,'789c5891-212c-4339-95a2-80f75a168231' + ,'7890123456' --phone + ,0 --phone confirmed + ,0 + ,NULL + ,1 + ,0 + ,0) --is registered + + ,('5bff5f95-1848-4c87-9846-a567aeb407ea' --Id + ,'2021-06-04 10:33:26.6295481 +00:00' --[CreatingTime] + ,'0001-01-01 00:00:00.0000000 +00:00' --LastLogin + ,'Провайдердругий' --last name + ,'Борисович' --middle name + ,'Борис' --first name + ,'provider' --role + ,'test4@test.com' + ,'TEST4@TEST.COM' + ,'test4@test.com' + ,'TEST4@TEST.COM' + ,0 --emeil confirmed + ,'AQAAAAEAACcQAAAAEOJFUEjnmnHWPonAOsg9K6tBuT8e1cUYbBejJbRJf3smSTzUzqphZyFGtB7i6vuT0g==' --password hash + ,'NQTDJHP23OUXWSVOUSBDSUVBASPLCHV3' + ,'b419d5b7-fe0f-40a8-869f-76b2826de58f' + ,'0123456789' --phone + ,0 --phone confirmed + ,0 + ,NULL + ,1 + ,0 + ,0) --is registered + GO --Roles' Ids according to your data in [AspNetRoles]. INSERT INTO [dbo].[AspNetUserRoles] - ([UserId] - ,[RoleId]) - VALUES - ('16575ce5-38e3-4ae7-b991-4508ed488369' --UserId (test1) - ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('parent'))) --roleId (parent) +([UserId] + ,[RoleId]) +VALUES + ('16575ce5-38e3-4ae7-b991-4508ed488369' --UserId (test1) + ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('parent'))) --roleId (parent) - ,('7604a851-66db-4236-9271-1f037ffe3a81' --UserId (test2) - ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('parent'))) --roleId (parent) + ,('7604a851-66db-4236-9271-1f037ffe3a81' --UserId (test2) + ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('parent'))) --roleId (parent) - ,('47802b21-2fb5-435e-9057-75c43d002cef' --UserId (test3) - ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('provider'))) --roleId (provider) + ,('47802b21-2fb5-435e-9057-75c43d002cef' --UserId (test3) + ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('provider'))) --roleId (provider) - ,('5bff5f95-1848-4c87-9846-a567aeb407ea' --UserId (test4) - ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('provider'))) --roleId (provider) -GO + ,('5bff5f95-1848-4c87-9846-a567aeb407ea' --UserId (test4) + ,(SELECT TOP (1) [Id] FROM [AspNetRoles] WHERE [Name] LIKE('provider'))) --roleId (provider) + GO --====================PARENTS AND CHILDREN================================ --Parents INSERT INTO [dbo].[Parents] - ([UserId]) - VALUES - ('16575ce5-38e3-4ae7-b991-4508ed488369') --UserId (test1) +([UserId]) +VALUES + ('16575ce5-38e3-4ae7-b991-4508ed488369') --UserId (test1) - ,('7604a851-66db-4236-9271-1f037ffe3a81') --UserId (test2) -GO + ,('7604a851-66db-4236-9271-1f037ffe3a81') --UserId (test2) + GO --Social Groups (скіпнути, коли буде заповнятися програмою) --INSERT INTO [dbo].[SocialGroups] @@ -175,1528 +175,1501 @@ GO --Children INSERT INTO [dbo].[Children] - ([FirstName] - ,[LastName] - ,[MiddleName] - ,[DateOfBirth] - ,[Gender] - ,[ParentId] - ,[SocialGroupId]) - VALUES - ('Тетяна' - ,'Батькоперший' - ,'Іванівна' - ,'2010-12-11' - ,1 --gender - ,1 --parent Id (parent 1, user 1) - ,null) --social group - - ,('Богдан' - ,'Батькодругий' - ,'Петрович' - ,'2010-05-05' - ,0 --gender - ,2 --parent Id (parent 2, user 2) - ,2) --social group - - ,('Лідія' - ,'Батькодругий' - ,'Петрівна' - ,'2015-10-01' - ,1 --gender - ,2 --parent Id (parent 2, user 2) - ,2) --social group -GO +([FirstName] + ,[LastName] + ,[MiddleName] + ,[DateOfBirth] + ,[Gender] + ,[ParentId] + ,[SocialGroupId]) +VALUES + ('Тетяна' + ,'Батькоперший' + ,'Іванівна' + ,'2010-12-11' + ,1 --gender + ,1 --parent Id (parent 1, user 1) + ,null) --social group + + ,('Богдан' + ,'Батькодругий' + ,'Петрович' + ,'2010-05-05' + ,0 --gender + ,2 --parent Id (parent 2, user 2) + ,2) --social group + + ,('Лідія' + ,'Батькодругий' + ,'Петрівна' + ,'2015-10-01' + ,1 --gender + ,2 --parent Id (parent 2, user 2) + ,2) --social group + GO --Children birth certificates INSERT INTO [dbo].[BirthCertificates] - ([Id] - ,[SvidSer] - ,[SvidNum] - ,[SvidNumMD5] - ,[SvidWho] - ,[SvidDate]) - VALUES - (1 - ,'І-ФП' - ,'315315' - ,null - ,'Виконавчий комітет Дарницького району м. Києва' - ,'2010-12-12') - - ,(2 - ,'І-ФВ' - ,'415415' - ,null - ,'Виконавчий комітет Деснянського району м. Києва' - ,'2010-05-12') - - ,(3 - ,'А-ФВ' - ,'455485' - ,null - ,'Виконавчий комітет м.Житомиру' - ,'2015-10-12') -GO +([Id] + ,[SvidSer] + ,[SvidNum] + ,[SvidNumMD5] + ,[SvidWho] + ,[SvidDate]) +VALUES + (1 + ,'І-ФП' + ,'315315' + ,null + ,'Виконавчий комітет Дарницького району м. Києва' + ,'2010-12-12') + + ,(2 + ,'І-ФВ' + ,'415415' + ,null + ,'Виконавчий комітет Деснянського району м. Києва' + ,'2010-05-12') + + ,(3 + ,'А-ФВ' + ,'455485' + ,null + ,'Виконавчий комітет м.Житомиру' + ,'2015-10-12') + GO --==================== PROVIDERS AND WORKSHOPS ================================ --Directions INSERT INTO Directions (Title, Description) VALUES ('Музика', 'Музика'), ('Танці', 'Танці'), ('Спорт', 'Спорт') -GO - -INSERT INTO Departments (Title, Description, DirectionId) -VALUES -('Народних інструментів', 'Народних інструментів', 1), -('Духових та ударних інструментів', 'Духових та ударних інструментів', 1), -('Хореографічний', 'Хореографічний', 2), -('Олімпійські види спорту', 'Олімпійські види спорту', 3), -('Неолімпійські види спорту', 'Неолімпійські види спорту', 3) -GO - -INSERT INTO Classes (Title, Description, DepartmentId) -VALUES -('Бандура', 'Клас Бандури', 1), -('Акордеон', 'Клас Акордеону', 1), -('Ударні', 'Клас Ударних', 2), -('Флейта', 'Клас Флейти', 2), -('Бальні танці', 'Клас Бального танцю', 3), -('Сучасні танці', 'Клас Сучасного танцю', 3), -('Плавання', 'I.030. Плавання', 4), -('Футбол', 'I.050. Футбол', 4), -('Айкідо', 'II.004. Айкідо', 5), -('Альпінізм', 'II.007. Альпінізм', 5) -GO + GO + +INSERT INTO Departments (Title, Description, DirectionId) +VALUES + ('Народних інструментів', 'Народних інструментів', 1), + ('Духових та ударних інструментів', 'Духових та ударних інструментів', 1), + ('Хореографічний', 'Хореографічний', 2), + ('Олімпійські види спорту', 'Олімпійські види спорту', 3), + ('Неолімпійські види спорту', 'Неолімпійські види спорту', 3) + GO + +INSERT INTO Classes (Title, Description, DepartmentId) +VALUES + ('Бандура', 'Клас Бандури', 1), + ('Акордеон', 'Клас Акордеону', 1), + ('Ударні', 'Клас Ударних', 2), + ('Флейта', 'Клас Флейти', 2), + ('Бальні танці', 'Клас Бального танцю', 3), + ('Сучасні танці', 'Клас Сучасного танцю', 3), + ('Плавання', 'I.030. Плавання', 4), + ('Футбол', 'I.050. Футбол', 4), + ('Айкідо', 'II.004. Айкідо', 5), + ('Альпінізм', 'II.007. Альпінізм', 5) + GO --providers addresses, workshops INSERT INTO [dbo].[Addresses] - ([Region] - ,[District] - ,[City] - ,[Street] - ,[BuildingNumber] - ,[Latitude] - ,[Longitude]) - VALUES +([Region] + ,[District] + ,[City] + ,[Street] + ,[BuildingNumber] + ,[Latitude] + ,[Longitude]) +VALUES --providers - ('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'29' - ,50.4547 - ,30.5238) --provider1 legal - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'35' - ,50.4547 - ,30.5238) --provider1 actual - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Вокзальна' - ,'10' - ,50.2648700 - ,28.6766900) --provider2 legal - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Привозна' - ,'12А' - ,50.2648700 - ,28.6766900) --provider2 actual + ('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'29' + ,50.4547 + ,30.5238) --provider1 legal + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'35' + ,50.4547 + ,30.5238) --provider1 actual + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Вокзальна' + ,'10' + ,50.2648700 + ,28.6766900) --provider2 legal + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Привозна' + ,'12А' + ,50.2648700 + ,28.6766900) --provider2 actual --workshops - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'35' - ,50.4547 - ,30.5238) --workshop1 provider1 actual - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'35' - ,50.4547 - ,30.5238) --workshop2 provider1 actual - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'35' - ,50.4547 - ,30.5238) --workshop3 provider1 actual - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Старонаводницька' - ,'35' - ,50.4547 - ,30.5238) --workshop4 provider1 actual - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Привозна' - ,'12А' - ,50.2648700 - ,28.6766900) --workshop5 provider2 actual - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Привозна' - ,'12А' - ,50.2648700 - ,28.6766900) --workshop6 provider2 actual - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ляхова' - ,'12' - ,51.4547 - ,31.5238) --id 11 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ляхова' - ,'12' - ,51.4547 - ,31.5238) --id 12 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ляхова' - ,'12' - ,51.4547 - ,31.5238) --id 13 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ляхова' - ,'12' - ,51.4547 - ,31.5238) --id 14 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ляхова' - ,'12' - ,51.4547 - ,31.5238) --id 15 - - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ворфоломіївська' - ,'12' - ,50.5 - ,30.5) --id 16 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ворфоломіївська' - ,'12' - ,50.5 - ,30.5) --id 17 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ворфоломіївська' - ,'12' - ,50.5 - ,30.5) --id 18 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ворфоломіївська' - ,'12' - ,50.5 - ,30.5) --id 19 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Ворфоломіївська' - ,'12' - ,50.5 - ,30.5) --id 20 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 21 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 22 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 23 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 24 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 25 - - ,('Київська обл.' - ,'м. Київ' - ,'Київ' - ,'Бажана' - ,'12' - ,50.5 - ,31.5) --id 26 - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Бойченка' - ,'42' - ,50.265 - ,28.677) --id 27 - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Бойченка' - ,'42' - ,50.265 - ,28.677) --id 28 - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Вокарчука' - ,'42' - ,50.5 - ,28.9) --id 29 - - ,('Житомирська обл.' - ,'м. Житомир' - ,'Житомир' - ,'Вокарчука' - ,'42' - ,50.5 - ,28.9) --id 30 -GO + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'35' + ,50.4547 + ,30.5238) --workshop1 provider1 actual + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'35' + ,50.4547 + ,30.5238) --workshop2 provider1 actual + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'35' + ,50.4547 + ,30.5238) --workshop3 provider1 actual + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Старонаводницька' + ,'35' + ,50.4547 + ,30.5238) --workshop4 provider1 actual + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Привозна' + ,'12А' + ,50.2648700 + ,28.6766900) --workshop5 provider2 actual + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Привозна' + ,'12А' + ,50.2648700 + ,28.6766900) --workshop6 provider2 actual + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ляхова' + ,'12' + ,51.4547 + ,31.5238) --id 11 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ляхова' + ,'12' + ,51.4547 + ,31.5238) --id 12 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ляхова' + ,'12' + ,51.4547 + ,31.5238) --id 13 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ляхова' + ,'12' + ,51.4547 + ,31.5238) --id 14 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ляхова' + ,'12' + ,51.4547 + ,31.5238) --id 15 + + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ворфоломіївська' + ,'12' + ,50.5 + ,30.5) --id 16 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ворфоломіївська' + ,'12' + ,50.5 + ,30.5) --id 17 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ворфоломіївська' + ,'12' + ,50.5 + ,30.5) --id 18 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ворфоломіївська' + ,'12' + ,50.5 + ,30.5) --id 19 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Ворфоломіївська' + ,'12' + ,50.5 + ,30.5) --id 20 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 21 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 22 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 23 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 24 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 25 + + ,('Київська обл.' + ,'м. Київ' + ,'Київ' + ,'Бажана' + ,'12' + ,50.5 + ,31.5) --id 26 + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Бойченка' + ,'42' + ,50.265 + ,28.677) --id 27 + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Бойченка' + ,'42' + ,50.265 + ,28.677) --id 28 + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Вокарчука' + ,'42' + ,50.5 + ,28.9) --id 29 + + ,('Житомирська обл.' + ,'м. Житомир' + ,'Житомир' + ,'Вокарчука' + ,'42' + ,50.5 + ,28.9) --id 30 + GO --Providers INSERT INTO [dbo].[Providers] - ([FullTitle] - ,[ShortTitle] - ,[Website] - ,[Email] - ,[Facebook] - ,[Instagram] - ,[Description] - ,[EdrpouIpn] - ,[Director] - ,[DirectorDateOfBirth] - ,[PhoneNumber] - ,[Founder] - ,[Ownership] - ,[Type] - ,[Status] - ,[LegalAddressId] - ,[ActualAddressId] - ,[UserId]) - VALUES - ('Музична школа №1' - ,'Музична школа' - ,'http://provider1' - ,'provider1@test.com' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,'Музикальні гуртки' --Description - ,'12345678' - ,'Провайдерперший Семен Семенович' --Director - ,'2000-10-12' - ,'0981234567' - ,'Ващенко Володимир Богданович' --Founder - ,0 --Ownership(state) - ,4 --Type(EducationalInstitution) - ,1 --Status - ,1 --LegalAddressId - ,2 --ActualAddressId - ,'47802b21-2fb5-435e-9057-75c43d002cef') --User Id (test4) - - ,('Школа бойових мистецтв №2' - ,'ШБК №2' - ,'http://provider2' - ,'provider1@test.com' - ,'http://facebook/provider2' - ,'http://instagram/provider2' - ,'Спортивні гуртки' - ,'98764523' - ,'Дорогий Захар Несторович' - ,'1990-11-02' - ,'0981234567' - ,'Дорогий Захар Несторович' - ,2 --Ownership(private) - ,3 --Type(Private) - ,1 --Status - ,3 --LegalAddressId - ,4 --ActualAddressId - ,'5bff5f95-1848-4c87-9846-a567aeb407ea') -GO +([FullTitle] + ,[ShortTitle] + ,[Website] + ,[Email] + ,[Facebook] + ,[Instagram] + ,[Description] + ,[EdrpouIpn] + ,[Director] + ,[DirectorDateOfBirth] + ,[PhoneNumber] + ,[Founder] + ,[Ownership] + ,[Type] + ,[Status] + ,[LegalAddressId] + ,[ActualAddressId] + ,[UserId]) +VALUES + ('Музична школа №1' + ,'Музична школа' + ,'http://provider1' + ,'provider1@test.com' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,'Музикальні гуртки' --Description + ,'12345678' + ,'Провайдерперший Семен Семенович' --Director + ,'2000-10-12' + ,'0981234567' + ,'Ващенко Володимир Богданович' --Founder + ,0 --Ownership(state) + ,4 --Type(EducationalInstitution) + ,1 --Status + ,1 --LegalAddressId + ,2 --ActualAddressId + ,'47802b21-2fb5-435e-9057-75c43d002cef') --User Id (test4) + + ,('Школа бойових мистецтв №2' + ,'ШБК №2' + ,'http://provider2' + ,'provider1@test.com' + ,'http://facebook/provider2' + ,'http://instagram/provider2' + ,'Спортивні гуртки' + ,'98764523' + ,'Дорогий Захар Несторович' + ,'1990-11-02' + ,'0981234567' + ,'Дорогий Захар Несторович' + ,2 --Ownership(private) + ,3 --Type(Private) + ,1 --Status + ,3 --LegalAddressId + ,4 --ActualAddressId + ,'5bff5f95-1848-4c87-9846-a567aeb407ea') + GO --workshops INSERT INTO [dbo].[Workshops] - ([Title] - ,[Keywords] - ,[Phone] - ,[Email] - ,[Website] - ,[Facebook] - ,[Instagram] - ,[MinAge] - ,[MaxAge] - ,[DaysPerWeek] - ,[Price] - ,[Description] - ,[WithDisabilityOptions] - ,[DisabilityOptionsDesc] - ,[Logo] - ,[Head] - ,[HeadDateOfBirth] - ,[IsPerMonth] - ,[ProviderId] - ,[AddressId] - ,[DirectionId] - ,[DepartmentId] - ,[ClassId] - ,[ProviderTitle]) - VALUES - ('Уроки аккордиону' - ,null - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,100 --maxAge - ,1 --days per week - ,50 --price - ,'Уроки аккордиону' --Description - ,1 --WithDisabilityOptions - ,'Немає конкретних обмежень' -- disability description - ,'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,5 --AddressId - ,1 --directionId - ,2 --departmentId - ,2 --classId - ,'Музична школа №1') --provider title - - ,('Уроки бандури' - ,null - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,100 --maxAge - ,2 --days per week - ,500 --price - ,'Уроки бандури' - ,1 --WithDisabilityOptions - ,'Немає конкретних обмежень' -- disability description - ,'Logo' - ,'Денисенко Денис Денисович' - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,6 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Гра на барабані' - ,null - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,100 --maxAge - ,2 --days per week - ,500 --price - ,'Уроки гри на ударних інструментах' - ,1 --WithDisabilityOptions - ,'Немає конкретних обмежень' -- disability description - ,'Logo' - ,'Гуляйборода Катерина Василівна' - ,'1977-09-22' - ,0 --IsPerMonth - ,1 --ProviderId - ,7 --AddressId - ,1 --directionId - ,2 --departmentId - ,3 --classId - ,'Музична школа №1') --provider title - - ,('Уроки гри на флейті' - ,null - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,100 --maxAge - ,2 --days per week - ,100 --price - ,'Уроки гри на флейті' - ,1 --WithDisabilityOptions - ,'Немає конкретних обмежень' -- disability description - ,'Logo' - ,'Гуляйборода Катерина Василівна' - ,'1977-09-22' - ,0 --IsPerMonth - ,1 --ProviderId - ,8 --AddressId - ,1 --directionId - ,2 --departmentId - ,4 --classId - ,'Музична школа №1') --provider title - - ,('Айкідо' - ,null - ,'1234567890' --Phone - ,'provider2@test.com' - ,'http://provider2' - ,'http://facebook/provider2' - ,'http://instagram/provider2' - ,7 --minAge - ,50 --maxAge - ,3 --days per week - ,300 --price - ,'Уроки айкідо' - ,0 --WithDisabilityOptions - ,null -- disability description - ,'Логотип' - ,'Дорогий Захар Несторович' - ,'1984-09-02' - ,1 --IsPerMonth - ,2 --ProviderId - ,9 --AddressId - ,3 --directionId - ,5 --departmentId - ,9 --classId - ,'Школа бойових мистецтв №2') --provider title - - ,('Плавання' - ,null - ,'1234567890' --Phone - ,'provider2@test.com' - ,'http://provider2' - ,'http://facebook/provider2' - ,'http://instagram/provider2' - ,3 --minAge - ,100 --maxAge - ,3 --days per week - ,300 --price - ,'Уроки плавання' - ,1 --WithDisabilityOptions - ,'будь-які' -- disability description - ,'Логотип' - ,'Рибочкін Леонід Федорович' - ,'1995-09-06' - ,1 --IsPerMonth - ,2 --ProviderId - ,10 --AddressId - ,3 --directionId - ,4 --departmentId - ,7 --classId - ,'Школа бойових мистецтв №2') --provider title - - ,('Співочий аккордион дошкільнят' - ,'аккордион¤співи' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,0 --minAge - ,5 --maxAge - ,1 --days per week - ,0 --price - ,'Аккордион і співи' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,11 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Співочий аккордион юніорів' - ,'аккордион¤співи' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,6 --minAge - ,10 --maxAge - ,1 --days per week - ,0 --price - ,'Аккордион і співи' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,12 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Співочий аккордион тінейджерів' - ,'аккордион¤співи' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,11 --minAge - ,16 --maxAge - ,1 --days per week - ,0 --price - ,'Аккордион і співи' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,13 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Струни душі' - ,'бандура' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,6 --minAge - ,10 --maxAge - ,1 --days per week - ,360 --price - ,'Гра на бандурі' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,14 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Балалайка для малят' - ,'бандура' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,0 --minAge - ,5 --maxAge - ,1 --days per week - ,0 --price - ,'Гра на бандурі' --Description - ,240 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,15 --AddressId - ,1 --directionId - ,1 --departmentId - ,1 --classId - ,'Музична школа №1') --provider title - - ,('Тендітні носочки' - ,'танці¤бальні¤класичні' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,0 --minAge - ,5 --maxAge - ,1 --days per week - ,240 --price - ,'Бальні танці' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,16 --AddressId - ,2 --directionId - ,2 --departmentId - ,5 --classId - ,'Музична школа №1') --provider title - - ,('Прима-балерина' - ,'танці¤бальні¤класичні' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,10 --minAge - ,18 --maxAge - ,1 --days per week - ,780 --price - ,'Бальні танці' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,17 --AddressId - ,2 --directionId - ,2 --departmentId - ,5 --classId - ,'Музична школа №1') --provider title - - ,('Танці вулиць' - ,'танці¤вуличні¤сучасні' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,6 --minAge - ,8 --maxAge - ,1 --days per week - ,640 --price - ,'Ми навчимо вашу дитину танцювати енергійно. STREET DANCE.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,18 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Хіп-хоп' - ,'танці¤сучасні' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,9 --minAge - ,12 --maxAge - ,1 --days per week - ,740 --price - ,'HIP-HOP і тільки.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,19 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Електрік-бугі' - ,'танці¤сучасні¤вугі' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,9 --minAge - ,12 --maxAge - ,1 --days per week - ,740 --price - ,'ELECTRIC BOOGIE це весело і корисно.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,20 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Диско денс' - ,'диско' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,10 --minAge - ,12 --maxAge - ,1 --days per week - ,490 --price - ,'Танці диско - це ярко і сміливо.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,21 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Степ' - ,'степ¤сучасно¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,10 --minAge - ,12 --maxAge - ,1 --days per week - ,355 --price - ,'Просто приходь, просто танцюй.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,22 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Диско як стан душі' - ,'диско¤дорослі¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,18 --minAge - ,100 --maxAge - ,1 --days per week - ,278 --price - ,'Просто приходь, просто танцюй.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,23 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Шаффл-денс' - ,'шаффл¤дорослі¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,18 --minAge - ,40 --maxAge - ,1 --days per week - ,600 --price - ,'Відкриваємо світ енергійноо, незвичного танцю шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,24 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Шаффл' - ,'шаффл¤дорослі¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,6 --minAge - ,10 --maxAge - ,1 --days per week - ,300 --price - ,'Відкриваємо світ енергійноо, незвичного танцю шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,25 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Уроки гри на флейті' - ,null - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,10 --maxAge - ,2 --days per week - ,90 --price - ,'Уроки гри на флейті' - ,1 --WithDisabilityOptions - ,'Немає конкретних обмежень' -- disability description - ,'Logo' - ,'Гуляйборода Катерина Василівна' - ,'1977-09-22' - ,0 --IsPerMonth - ,1 --ProviderId - ,26 --AddressId - ,1 --categoryId - ,2 --subcategoryId - ,4 --SubsubcategoryId - ,'Музична школа №1') --provider title - - ,('Шаффл діти' - ,'шаффл¤сучасні¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,5 --minAge - ,8 --maxAge - ,1 --days per week - ,200 --price - ,'Крутий танок шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,27 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Шаффл школярі' - ,'шаффл¤сучасні¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,9 --minAge - ,12 --maxAge - ,1 --days per week - ,250 --price - ,'Крутий танок шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,28 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Шаффл підлітки' - ,'шаффл¤сучасні¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,13 --minAge - ,18 --maxAge - ,1 --days per week - ,350 --price - ,'Крутий танок шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,29 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title - - ,('Шаффл дорослі' - ,'шаффл¤сучасні¤танці' - ,'1234567890' --Phone - ,'provider1@test.com' - ,'http://provider1' - ,'http://facebook/provider1' - ,'http://instagram/provider1' - ,19 --minAge - ,100 --maxAge - ,1 --days per week - ,550 --price - ,'Крутий танок шаффл.' --Description - ,0 --WithDisabilityOptions - ,null -- disability description - ,null --'Logo' - ,'Василенко Світлана Львівна' --Head - ,'1987-09-22' - ,1 --IsPerMonth - ,1 --ProviderId - ,30 --AddressId - ,2 --directionId - ,2 --departmentId - ,6 --classId - ,'Музична школа №1') --provider title -GO +([Title] + ,[Keywords] + ,[Phone] + ,[Email] + ,[Website] + ,[Facebook] + ,[Instagram] + ,[MinAge] + ,[MaxAge] + ,[Price] + ,[Description] + ,[WithDisabilityOptions] + ,[DisabilityOptionsDesc] + ,[Logo] + ,[Head] + ,[HeadDateOfBirth] + ,[IsPerMonth] + ,[ProviderId] + ,[AddressId] + ,[DirectionId] + ,[DepartmentId] + ,[ClassId] + ,[ProviderTitle]) +VALUES + ('Уроки аккордиону' + ,null + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,100 --maxAge + ,50 --price + ,'Уроки аккордиону' --Description + ,1 --WithDisabilityOptions + ,'Немає конкретних обмежень' -- disability description + ,'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,5 --AddressId + ,1 --directionId + ,2 --departmentId + ,2 --classId + ,'Музична школа №1') --provider title + + ,('Уроки бандури' + ,null + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,100 --maxAge + ,500 --price + ,'Уроки бандури' + ,1 --WithDisabilityOptions + ,'Немає конкретних обмежень' -- disability description + ,'Logo' + ,'Денисенко Денис Денисович' + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,6 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Гра на барабані' + ,null + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,100 --maxAge + ,500 --price + ,'Уроки гри на ударних інструментах' + ,1 --WithDisabilityOptions + ,'Немає конкретних обмежень' -- disability description + ,'Logo' + ,'Гуляйборода Катерина Василівна' + ,'1977-09-22' + ,0 --IsPerMonth + ,1 --ProviderId + ,7 --AddressId + ,1 --directionId + ,2 --departmentId + ,3 --classId + ,'Музична школа №1') --provider title + + ,('Уроки гри на флейті' + ,null + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,100 --maxAge + ,100 --price + ,'Уроки гри на флейті' + ,1 --WithDisabilityOptions + ,'Немає конкретних обмежень' -- disability description + ,'Logo' + ,'Гуляйборода Катерина Василівна' + ,'1977-09-22' + ,0 --IsPerMonth + ,1 --ProviderId + ,8 --AddressId + ,1 --directionId + ,2 --departmentId + ,4 --classId + ,'Музична школа №1') --provider title + + ,('Айкідо' + ,null + ,'1234567890' --Phone + ,'provider2@test.com' + ,'http://provider2' + ,'http://facebook/provider2' + ,'http://instagram/provider2' + ,7 --minAge + ,50 --maxAge + ,300 --price + ,'Уроки айкідо' + ,0 --WithDisabilityOptions + ,null -- disability description + ,'Логотип' + ,'Дорогий Захар Несторович' + ,'1984-09-02' + ,1 --IsPerMonth + ,2 --ProviderId + ,9 --AddressId + ,3 --directionId + ,5 --departmentId + ,9 --classId + ,'Школа бойових мистецтв №2') --provider title + + ,('Плавання' + ,null + ,'1234567890' --Phone + ,'provider2@test.com' + ,'http://provider2' + ,'http://facebook/provider2' + ,'http://instagram/provider2' + ,3 --minAge + ,100 --maxAge + ,300 --price + ,'Уроки плавання' + ,1 --WithDisabilityOptions + ,'будь-які' -- disability description + ,'Логотип' + ,'Рибочкін Леонід Федорович' + ,'1995-09-06' + ,1 --IsPerMonth + ,2 --ProviderId + ,10 --AddressId + ,3 --directionId + ,4 --departmentId + ,7 --classId + ,'Школа бойових мистецтв №2') --provider title + + ,('Співочий аккордион дошкільнят' + ,'аккордион¤співи' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,0 --minAge + ,5 --maxAge + ,0 --price + ,'Аккордион і співи' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,11 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Співочий аккордион юніорів' + ,'аккордион¤співи' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,6 --minAge + ,10 --maxAge + ,0 --price + ,'Аккордион і співи' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,12 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Співочий аккордион тінейджерів' + ,'аккордион¤співи' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,11 --minAge + ,16 --maxAge + ,0 --price + ,'Аккордион і співи' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,13 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Струни душі' + ,'бандура' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,6 --minAge + ,10 --maxAge + ,360 --price + ,'Гра на бандурі' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,14 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Балалайка для малят' + ,'бандура' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,0 --minAge + ,5 --maxAge + ,0 --price + ,'Гра на бандурі' --Description + ,240 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,15 --AddressId + ,1 --directionId + ,1 --departmentId + ,1 --classId + ,'Музична школа №1') --provider title + + ,('Тендітні носочки' + ,'танці¤бальні¤класичні' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,0 --minAge + ,5 --maxAge + ,240 --price + ,'Бальні танці' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,16 --AddressId + ,2 --directionId + ,2 --departmentId + ,5 --classId + ,'Музична школа №1') --provider title + + ,('Прима-балерина' + ,'танці¤бальні¤класичні' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,10 --minAge + ,18 --maxAge + ,780 --price + ,'Бальні танці' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,17 --AddressId + ,2 --directionId + ,2 --departmentId + ,5 --classId + ,'Музична школа №1') --provider title + + ,('Танці вулиць' + ,'танці¤вуличні¤сучасні' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,6 --minAge + ,8 --maxAge + ,640 --price + ,'Ми навчимо вашу дитину танцювати енергійно. STREET DANCE.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,18 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Хіп-хоп' + ,'танці¤сучасні' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,9 --minAge + ,12 --maxAge + ,740 --price + ,'HIP-HOP і тільки.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,19 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Електрік-бугі' + ,'танці¤сучасні¤вугі' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,9 --minAge + ,12 --maxAge + ,740 --price + ,'ELECTRIC BOOGIE це весело і корисно.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,20 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Диско денс' + ,'диско' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,10 --minAge + ,12 --maxAge + ,490 --price + ,'Танці диско - це ярко і сміливо.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,21 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Степ' + ,'степ¤сучасно¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,10 --minAge + ,12 --maxAge + ,355 --price + ,'Просто приходь, просто танцюй.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,22 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Диско як стан душі' + ,'диско¤дорослі¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,18 --minAge + ,100 --maxAge + ,278 --price + ,'Просто приходь, просто танцюй.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,23 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Шаффл-денс' + ,'шаффл¤дорослі¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,18 --minAge + ,40 --maxAge + ,600 --price + ,'Відкриваємо світ енергійноо, незвичного танцю шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,24 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Шаффл' + ,'шаффл¤дорослі¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,6 --minAge + ,10 --maxAge + ,300 --price + ,'Відкриваємо світ енергійноо, незвичного танцю шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,25 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Уроки гри на флейті' + ,null + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,10 --maxAge + ,90 --price + ,'Уроки гри на флейті' + ,1 --WithDisabilityOptions + ,'Немає конкретних обмежень' -- disability description + ,'Logo' + ,'Гуляйборода Катерина Василівна' + ,'1977-09-22' + ,0 --IsPerMonth + ,1 --ProviderId + ,26 --AddressId + ,1 --categoryId + ,2 --subcategoryId + ,4 --SubsubcategoryId + ,'Музична школа №1') --provider title + + ,('Шаффл діти' + ,'шаффл¤сучасні¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,5 --minAge + ,8 --maxAge + ,200 --price + ,'Крутий танок шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,27 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Шаффл школярі' + ,'шаффл¤сучасні¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,9 --minAge + ,12 --maxAge + ,250 --price + ,'Крутий танок шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,28 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Шаффл підлітки' + ,'шаффл¤сучасні¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,13 --minAge + ,18 --maxAge + ,350 --price + ,'Крутий танок шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,29 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + + ,('Шаффл дорослі' + ,'шаффл¤сучасні¤танці' + ,'1234567890' --Phone + ,'provider1@test.com' + ,'http://provider1' + ,'http://facebook/provider1' + ,'http://instagram/provider1' + ,19 --minAge + ,100 --maxAge + ,550 --price + ,'Крутий танок шаффл.' --Description + ,0 --WithDisabilityOptions + ,null -- disability description + ,null --'Logo' + ,'Василенко Світлана Львівна' --Head + ,'1987-09-22' + ,1 --IsPerMonth + ,1 --ProviderId + ,30 --AddressId + ,2 --directionId + ,2 --departmentId + ,6 --classId + ,'Музична школа №1') --provider title + GO --teachers INSERT INTO [dbo].[Teachers] - ([FirstName] - ,[LastName] - ,[MiddleName] - ,[DateOfBirth] - ,[Description] - ,[Image] - ,[WorkshopId]) - VALUES - ('Леонід' --firs name - ,'Вчительперший' --last name - ,'Леонідович' --middle name - ,'1995-09-06' - ,'Найкращий вчитель' - ,null - ,1) --workshop Id - - ,('Наталія' --firs name - ,'Вчительдругий' --last name - ,'Богданівна' --middle name - ,'1985-04-06' - ,'Найкращий вчитель року' - ,null - ,2) --workshop Id - - ,('Катерина' --firs name - ,'Гуляйборода' --last name - ,'Василівна' --middle name - ,'1995-09-06' - ,'Найкращий вчитель' - ,null - ,3) --workshop Id - - ,('Георгій' --firs name - ,'Вчительчетвертий' --last name - ,'Ігорович' --middle name - ,'1985-04-06' - ,'Найкращий вчитель року' - ,null - ,4) --workshop Id - - ,('Святослав' --firs name - ,'Вчительтретій' --last name - ,'Ігорович' --middle name - ,'2000-04-06' - ,'КМС з айкідо' - ,null - ,5) --workshop Id - - ,('Денис' --firs name - ,'Вчительчетвертий' --last name - ,'Владиславович' --middle name - ,'1998-04-06' - ,'Чемпіон національних олімпіад з плавання' - ,null - ,6) --workshop Id -GO +([FirstName] + ,[LastName] + ,[MiddleName] + ,[DateOfBirth] + ,[Description] + ,[Image] + ,[WorkshopId]) +VALUES + ('Леонід' --firs name + ,'Вчительперший' --last name + ,'Леонідович' --middle name + ,'1995-09-06' + ,'Найкращий вчитель' + ,null + ,1) --workshop Id + + ,('Наталія' --firs name + ,'Вчительдругий' --last name + ,'Богданівна' --middle name + ,'1985-04-06' + ,'Найкращий вчитель року' + ,null + ,2) --workshop Id + + ,('Катерина' --firs name + ,'Гуляйборода' --last name + ,'Василівна' --middle name + ,'1995-09-06' + ,'Найкращий вчитель' + ,null + ,3) --workshop Id + + ,('Георгій' --firs name + ,'Вчительчетвертий' --last name + ,'Ігорович' --middle name + ,'1985-04-06' + ,'Найкращий вчитель року' + ,null + ,4) --workshop Id + + ,('Святослав' --firs name + ,'Вчительтретій' --last name + ,'Ігорович' --middle name + ,'2000-04-06' + ,'КМС з айкідо' + ,null + ,5) --workshop Id + + ,('Денис' --firs name + ,'Вчительчетвертий' --last name + ,'Владиславович' --middle name + ,'1998-04-06' + ,'Чемпіон національних олімпіад з плавання' + ,null + ,6) --workshop Id + GO --Applications INSERT INTO [dbo].[Applications] - ([Status] - ,[WorkshopId] - ,[ChildId] - ,[CreationTime] - ,[ParentId]) - VALUES +([Status] + ,[WorkshopId] + ,[ChildId] + ,[CreationTime] + ,[ParentId]) +VALUES --workshop1 - (2 -- - ,1 -- - ,1 -- - ,'2021-06-06 12:20:20' -- - ,1) --parentId - - ,(2 -- - ,1 -- - ,2 -- - ,'2021-06-04 15:34:20' -- - ,2) --parentId - - ,(1 -- - ,1 -- - ,3 -- - ,'2021-06-05 08:23:20' -- - ,2) --parentId + (2 -- + ,1 -- + ,1 -- + ,'2021-06-06 12:20:20' -- + ,1) --parentId + + ,(2 -- + ,1 -- + ,2 -- + ,'2021-06-04 15:34:20' -- + ,2) --parentId + + ,(1 -- + ,1 -- + ,3 -- + ,'2021-06-05 08:23:20' -- + ,2) --parentId --workshop2 - ,(1 -- - ,2 -- - ,1 -- - ,'2021-06-15 17:20:00' -- - ,1) --parentId - - ,(1 -- - ,2 -- - ,2 -- - ,'2021-06-15 17:26:10' -- - ,2) --parentId - - ,(1 -- - ,2 -- - ,3 -- - ,'2021-06-15 18:00:45' -- - ,2) --parentId -GO + ,(1 -- + ,2 -- + ,1 -- + ,'2021-06-15 17:20:00' -- + ,1) --parentId + + ,(1 -- + ,2 -- + ,2 -- + ,'2021-06-15 17:26:10' -- + ,2) --parentId + + ,(1 -- + ,2 -- + ,3 -- + ,'2021-06-15 18:00:45' -- + ,2) --parentId + GO --Rating INSERT INTO [dbo].[Ratings] - ([Rate] - ,[Type] - ,[EntityId] - ,[ParentId] - ,[CreationTime]) - VALUES +([Rate] + ,[Type] + ,[EntityId] + ,[ParentId] + ,[CreationTime]) +VALUES --parent 1 - (5 --rating - ,2 --workshop - ,1 -- workshopId - ,1 --parent - ,'2021-01-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,2 -- workshopId - ,1 --parent - ,'2021-02-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,3 -- workshopId - ,1 --parent - ,'2021-03-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,4 -- workshopId - ,1 --parent - ,'2021-04-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,4 -- workshopId - ,1 --parent - ,'2021-05-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,5 -- workshopId - ,1 --parent - ,'2021-06-15 18:00:45') - - ,(5 --rating - ,2 --workshop - ,6 -- workshopId - ,1 --parent - ,'2021-07-01 18:00:45') - - ,(5 --rating - ,2 --workshop - ,7 -- workshopId - ,1 --parent - ,'2021-07-02 18:00:45') - - ,(5 --rating - ,2 --workshop - ,8 -- workshopId - ,1 --parent - ,'2021-07-03 18:00:45') - - ,(5 --rating - ,2 --workshop - ,9 -- workshopId - ,1 --parent - ,'2021-07-04 18:00:45') - - ,(5 --rating - ,2 --workshop - ,10 -- workshopId - ,1 --parent - ,'2021-07-05 18:00:45') - - ,(4 --rating - ,2 --workshop - ,11 -- workshopId - ,1 --parent - ,'2021-07-06 18:00:45') - - ,(4 --rating - ,2 --workshop - ,12 -- workshopId - ,1 --parent - ,'2021-07-08 18:00:45') - - ,(4 --rating - ,2 --workshop - ,13 -- workshopId - ,1 --parent - ,'2021-07-09 18:00:45') - - ,(4 --rating - ,2 --workshop - ,14 -- workshopId - ,1 --parent - ,'2021-07-10 18:00:45') - - ,(4 --rating - ,2 --workshop - ,15 -- workshopId - ,1 --parent - ,'2021-07-11 18:00:45') - - ,(4 --rating - ,2 --workshop - ,16 -- workshopId - ,1 --parent - ,'2021-07-12 18:00:45') - - ,(4 --rating - ,2 --workshop - ,17 -- workshopId - ,1 --parent - ,'2021-07-13 18:00:45') - - ,(4 --rating - ,2 --workshop - ,18 -- workshopId - ,1 --parent - ,'2021-07-14 18:00:45') - - ,(4 --rating - ,2 --workshop - ,19 -- workshopId - ,1 --parent - ,'2021-07-15 18:00:45') - - ,(4 --rating - ,2 --workshop - ,20 -- workshopId - ,1 --parent - ,'2021-07-16 18:00:45') - - ,(3 --rating - ,2 --workshop - ,21 -- workshopId - ,1 --parent - ,'2021-07-17 18:00:45') - - ,(3 --rating - ,2 --workshop - ,22 -- workshopId - ,1 --parent - ,'2021-07-18 18:00:45') - - ,(3 --rating - ,2 --workshop - ,23 -- workshopId - ,1 --parent - ,'2021-07-19 18:00:45') - - ,(3 --rating - ,2 --workshop - ,24 -- workshopId - ,1 --parent - ,'2021-07-20 18:00:45') - - ,(3 --rating - ,2 --workshop - ,25 -- workshopId - ,1 --parent - ,'2021-07-21 18:00:45') - - ,(3 --rating - ,2 --workshop - ,26 -- workshopId - ,1 --parent - ,'2021-07-22 18:00:45') + (5 --rating + ,2 --workshop + ,1 -- workshopId + ,1 --parent + ,'2021-01-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,2 -- workshopId + ,1 --parent + ,'2021-02-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,3 -- workshopId + ,1 --parent + ,'2021-03-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,4 -- workshopId + ,1 --parent + ,'2021-04-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,4 -- workshopId + ,1 --parent + ,'2021-05-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,5 -- workshopId + ,1 --parent + ,'2021-06-15 18:00:45') + + ,(5 --rating + ,2 --workshop + ,6 -- workshopId + ,1 --parent + ,'2021-07-01 18:00:45') + + ,(5 --rating + ,2 --workshop + ,7 -- workshopId + ,1 --parent + ,'2021-07-02 18:00:45') + + ,(5 --rating + ,2 --workshop + ,8 -- workshopId + ,1 --parent + ,'2021-07-03 18:00:45') + + ,(5 --rating + ,2 --workshop + ,9 -- workshopId + ,1 --parent + ,'2021-07-04 18:00:45') + + ,(5 --rating + ,2 --workshop + ,10 -- workshopId + ,1 --parent + ,'2021-07-05 18:00:45') + + ,(4 --rating + ,2 --workshop + ,11 -- workshopId + ,1 --parent + ,'2021-07-06 18:00:45') + + ,(4 --rating + ,2 --workshop + ,12 -- workshopId + ,1 --parent + ,'2021-07-08 18:00:45') + + ,(4 --rating + ,2 --workshop + ,13 -- workshopId + ,1 --parent + ,'2021-07-09 18:00:45') + + ,(4 --rating + ,2 --workshop + ,14 -- workshopId + ,1 --parent + ,'2021-07-10 18:00:45') + + ,(4 --rating + ,2 --workshop + ,15 -- workshopId + ,1 --parent + ,'2021-07-11 18:00:45') + + ,(4 --rating + ,2 --workshop + ,16 -- workshopId + ,1 --parent + ,'2021-07-12 18:00:45') + + ,(4 --rating + ,2 --workshop + ,17 -- workshopId + ,1 --parent + ,'2021-07-13 18:00:45') + + ,(4 --rating + ,2 --workshop + ,18 -- workshopId + ,1 --parent + ,'2021-07-14 18:00:45') + + ,(4 --rating + ,2 --workshop + ,19 -- workshopId + ,1 --parent + ,'2021-07-15 18:00:45') + + ,(4 --rating + ,2 --workshop + ,20 -- workshopId + ,1 --parent + ,'2021-07-16 18:00:45') + + ,(3 --rating + ,2 --workshop + ,21 -- workshopId + ,1 --parent + ,'2021-07-17 18:00:45') + + ,(3 --rating + ,2 --workshop + ,22 -- workshopId + ,1 --parent + ,'2021-07-18 18:00:45') + + ,(3 --rating + ,2 --workshop + ,23 -- workshopId + ,1 --parent + ,'2021-07-19 18:00:45') + + ,(3 --rating + ,2 --workshop + ,24 -- workshopId + ,1 --parent + ,'2021-07-20 18:00:45') + + ,(3 --rating + ,2 --workshop + ,25 -- workshopId + ,1 --parent + ,'2021-07-21 18:00:45') + + ,(3 --rating + ,2 --workshop + ,26 -- workshopId + ,1 --parent + ,'2021-07-22 18:00:45') --parent 2 - ,(5 --rating - ,2 --workshop - ,1 -- workshopId - ,2 --parent - ,'2021-01-02 18:00:45') - - ,(5 --rating - ,2 --workshop - ,2 -- workshopId - ,2 --parent - ,'2021-02-02 18:00:45') - - ,(5 --rating - ,2 --workshop - ,3 -- workshopId - ,2 --parent - ,'2021-03-02 18:00:45') - - ,(5 --rating - ,2 --workshop - ,4 -- workshopId - ,2 --parent - ,'2021-04-02 18:00:45') - - ,(5 --rating - ,2 --workshop - ,4 -- workshopId - ,2 --parent - ,'2021-05-01 18:00:45') - - ,(4 --rating - ,2 --workshop - ,5 -- workshopId - ,2 --parent - ,'2021-05-02 18:00:45') - - ,(4 --rating - ,2 --workshop - ,6 -- workshopId - ,2 --parent - ,'2021-06-02 18:00:45') - - ,(3 --rating - ,2 --workshop - ,7 -- workshopId - ,2 --parent - ,'2021-07-02 18:00:45') - - ,(2 --rating - ,2 --workshop - ,8 -- workshopId - ,2 --parent - ,'2021-07-01 18:00:45') - - ,(1 --rating - ,2 --workshop - ,9 -- workshopId - ,2 --parent - ,'2021-07-02 18:00:45') - - ,(2 --rating - ,2 --workshop - ,10 -- workshopId - ,2 --parent - ,'2021-07-02 18:00:45') - - ,(4 --rating - ,2 --workshop - ,11 -- workshopId - ,2 --parent - ,'2021-07-03 18:00:45') - - ,(2 --rating - ,2 --workshop - ,12 -- workshopId - ,2 --parent - ,'2021-07-04 18:00:45') - - ,(2 --rating - ,2 --workshop - ,13 -- workshopId - ,2 --parent - ,'2021-07-05 18:00:45') - - ,(2 --rating - ,2 --workshop - ,14 -- workshopId - ,2 --parent - ,'2021-07-06 18:00:45') - - ,(5 --rating - ,2 --workshop - ,15 -- workshopId - ,2 --parent - ,'2021-07-07 18:00:45') - - ,(5 --rating - ,2 --workshop - ,16 -- workshopId - ,2 --parent - ,'2021-07-08 18:00:45') - - ,(5 --rating - ,2 --workshop - ,17 -- workshopId - ,2 --parent - ,'2021-07-09 18:00:45') - - ,(4 --rating - ,2 --workshop - ,18 -- workshopId - ,2 --parent - ,'2021-07-10 18:00:45') - - ,(4 --rating - ,2 --workshop - ,19 -- workshopId - ,2 --parent - ,'2021-07-10 19:00:45') - - ,(4 --rating - ,2 --workshop - ,20 -- workshopId - ,2 --parent - ,'2021-07-11 10:00:45') - - ,(5 --rating - ,2 --workshop - ,21 -- workshopId - ,2 --parent - ,'2021-07-11 13:00:45') - - ,(3 --rating - ,2 --workshop - ,22 -- workshopId - ,2 --parent - ,'2021-07-12 13:00:45') - - ,(4 --rating - ,2 --workshop - ,23 -- workshopId - ,2 --parent - ,'2021-07-13 18:00:45') - - ,(4 --rating - ,2 --workshop - ,24 -- workshopId - ,2 --parent - ,'2021-07-14 18:20:45') - - ,(3 --rating - ,2 --workshop - ,25 -- workshopId - ,2 --parent - ,'2021-07-15 18:00:45') - - ,(3 --rating - ,2 --workshop - ,26 -- workshopId - ,2 --parent - ,'2021-07-16 18:00:45') -GO \ No newline at end of file + ,(5 --rating + ,2 --workshop + ,1 -- workshopId + ,2 --parent + ,'2021-01-02 18:00:45') + + ,(5 --rating + ,2 --workshop + ,2 -- workshopId + ,2 --parent + ,'2021-02-02 18:00:45') + + ,(5 --rating + ,2 --workshop + ,3 -- workshopId + ,2 --parent + ,'2021-03-02 18:00:45') + + ,(5 --rating + ,2 --workshop + ,4 -- workshopId + ,2 --parent + ,'2021-04-02 18:00:45') + + ,(5 --rating + ,2 --workshop + ,4 -- workshopId + ,2 --parent + ,'2021-05-01 18:00:45') + + ,(4 --rating + ,2 --workshop + ,5 -- workshopId + ,2 --parent + ,'2021-05-02 18:00:45') + + ,(4 --rating + ,2 --workshop + ,6 -- workshopId + ,2 --parent + ,'2021-06-02 18:00:45') + + ,(3 --rating + ,2 --workshop + ,7 -- workshopId + ,2 --parent + ,'2021-07-02 18:00:45') + + ,(2 --rating + ,2 --workshop + ,8 -- workshopId + ,2 --parent + ,'2021-07-01 18:00:45') + + ,(1 --rating + ,2 --workshop + ,9 -- workshopId + ,2 --parent + ,'2021-07-02 18:00:45') + + ,(2 --rating + ,2 --workshop + ,10 -- workshopId + ,2 --parent + ,'2021-07-02 18:00:45') + + ,(4 --rating + ,2 --workshop + ,11 -- workshopId + ,2 --parent + ,'2021-07-03 18:00:45') + + ,(2 --rating + ,2 --workshop + ,12 -- workshopId + ,2 --parent + ,'2021-07-04 18:00:45') + + ,(2 --rating + ,2 --workshop + ,13 -- workshopId + ,2 --parent + ,'2021-07-05 18:00:45') + + ,(2 --rating + ,2 --workshop + ,14 -- workshopId + ,2 --parent + ,'2021-07-06 18:00:45') + + ,(5 --rating + ,2 --workshop + ,15 -- workshopId + ,2 --parent + ,'2021-07-07 18:00:45') + + ,(5 --rating + ,2 --workshop + ,16 -- workshopId + ,2 --parent + ,'2021-07-08 18:00:45') + + ,(5 --rating + ,2 --workshop + ,17 -- workshopId + ,2 --parent + ,'2021-07-09 18:00:45') + + ,(4 --rating + ,2 --workshop + ,18 -- workshopId + ,2 --parent + ,'2021-07-10 18:00:45') + + ,(4 --rating + ,2 --workshop + ,19 -- workshopId + ,2 --parent + ,'2021-07-10 19:00:45') + + ,(4 --rating + ,2 --workshop + ,20 -- workshopId + ,2 --parent + ,'2021-07-11 10:00:45') + + ,(5 --rating + ,2 --workshop + ,21 -- workshopId + ,2 --parent + ,'2021-07-11 13:00:45') + + ,(3 --rating + ,2 --workshop + ,22 -- workshopId + ,2 --parent + ,'2021-07-12 13:00:45') + + ,(4 --rating + ,2 --workshop + ,23 -- workshopId + ,2 --parent + ,'2021-07-13 18:00:45') + + ,(4 --rating + ,2 --workshop + ,24 -- workshopId + ,2 --parent + ,'2021-07-14 18:20:45') + + ,(3 --rating + ,2 --workshop + ,25 -- workshopId + ,2 --parent + ,'2021-07-15 18:00:45') + + ,(3 --rating + ,2 --workshop + ,26 -- workshopId + ,2 --parent + ,'2021-07-16 18:00:45') + GO \ No newline at end of file diff --git a/Config/initDbServer.bat b/Config/initDbServer.bat index a87e654a3a..c1420c4023 100644 --- a/Config/initDbServer.bat +++ b/Config/initDbServer.bat @@ -1,2 +1,2 @@ -docker run -d --name sql_server -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Oos-password1" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest +docker run -d --name sql_server -e "ACCEPT_EULA=Y" -e MSSQL_COLLATION="Ukrainian_100_CI_AS" -e "SA_PASSWORD=Oos-password1" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest pause diff --git a/Config/initDbServer.sh b/Config/initDbServer.sh new file mode 100755 index 0000000000..9b883536dd --- /dev/null +++ b/Config/initDbServer.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +docker run -d --name sql_server -e "ACCEPT_EULA=Y" -e MSSQL_COLLATION="Ukrainian_100_CI_AS" -e "SA_PASSWORD=Oos-password1" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest + diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/.gitignore b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/.gitignore deleted file mode 100644 index c9c13f213c..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Rider ignored files -/contentModel.xml -/.idea.OutOfSchool.iml -/projectSettingsUpdater.xml -/modules.xml -# Datasource local storage ignored files -/../../../../../../../../../:\Styding\Programming\SOFTSERVE\OoS-Backend\OutOfSchool\.idea\.idea.OutOfSchool\.idea/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/dataSources.xml b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/dataSources.xml deleted file mode 100644 index 9872660992..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - sqlserver.ms - true - com.microsoft.sqlserver.jdbc.SQLServerDriver - jdbc:sqlserver://localhost;database=Master - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/encodings.xml b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/encodings.xml deleted file mode 100644 index df87cf951f..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/encodings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/indexLayout.xml b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/indexLayout.xml deleted file mode 100644 index 7b08163ceb..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/indexLayout.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/sqldialects.xml b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/sqldialects.xml deleted file mode 100644 index 034390a319..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/sqldialects.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/vcs.xml b/OutOfSchool/.idea/.idea.OutOfSchool/.idea/vcs.xml deleted file mode 100644 index 6c0b863585..0000000000 --- a/OutOfSchool/.idea/.idea.OutOfSchool/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Enums/ApplicationStatus.cs b/OutOfSchool/OutOfSchool.DataAccess/Enums/ApplicationStatus.cs index d228cc45d9..c36b6e1782 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Enums/ApplicationStatus.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Enums/ApplicationStatus.cs @@ -1,10 +1,11 @@ -using System.Text.Json.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace OutOfSchool.Services.Enums { // TODO: Swagger ignores this attribute on model property in webapi layer // TODO: Ask Frontend if we can just make all enums as strings instead of magic numbers - [JsonConverter(typeof(JsonStringEnumConverter))] + [JsonConverter(typeof(StringEnumConverter))] public enum ApplicationStatus { Pending = 1, diff --git a/OutOfSchool/OutOfSchool.DataAccess/Enums/DaysBitMask.cs b/OutOfSchool/OutOfSchool.DataAccess/Enums/DaysBitMask.cs new file mode 100644 index 0000000000..79f0800e68 --- /dev/null +++ b/OutOfSchool/OutOfSchool.DataAccess/Enums/DaysBitMask.cs @@ -0,0 +1,20 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace OutOfSchool.Services.Enums +{ + [JsonConverter(typeof(StringEnumConverter))] + [Flags] + public enum DaysBitMask + { + None = 0, + Monday = 1, + Tuesday = 2, + Wednesday = 4, + Thursday = 8, + Friday = 16, + Saturday = 32, + Sunday = 64, + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/IUnitOfWork.cs b/OutOfSchool/OutOfSchool.DataAccess/IUnitOfWork.cs new file mode 100644 index 0000000000..863c21bb54 --- /dev/null +++ b/OutOfSchool/OutOfSchool.DataAccess/IUnitOfWork.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace OutOfSchool.Services +{ + public interface IUnitOfWork + { + public Task CompleteAsync(); + + public int Complete(); + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/DateTimeRange.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/DateTimeRange.cs new file mode 100644 index 0000000000..c29697856d --- /dev/null +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/DateTimeRange.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using OutOfSchool.Services.Enums; + +namespace OutOfSchool.Services.Models +{ + public class DateTimeRange + { + public long Id { get; set; } + + public TimeSpan StartTime { get; set; } + + public TimeSpan EndTime { get; set; } + + public long WorkshopId { get; set; } + + [Required] + public List Workdays { get; set; } + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/Workshop.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/Workshop.cs index a763f789f6..d21ebe245f 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Models/Workshop.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/Workshop.cs @@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Newtonsoft.Json; namespace OutOfSchool.Services.Models { @@ -47,10 +48,6 @@ public class Workshop [Range(0, 18, ErrorMessage = "Max age should be a number from 0 to 18")] public int MaxAge { get; set; } - [Required(ErrorMessage = "Specify how many times per week lessons will be held")] - [Range(1, 7, ErrorMessage = "Field should be a digit from 1 to 7")] - public int DaysPerWeek { get; set; } - [Column(TypeName = "decimal(18,2)")] [Range(0, 10000, ErrorMessage = "Field value should be in a range from 1 to 10 000")] public decimal Price { get; set; } = default; @@ -113,6 +110,8 @@ public class Workshop public virtual List Applications { get; set; } + public virtual List DateTimeRanges { get; set; } + // These properties are only for navigation EF Core. public virtual ICollection ChatRooms { get; set; } } diff --git a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchool.DataAccess.csproj b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchool.DataAccess.csproj index 9f0fb13e8f..f82e90c106 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchool.DataAccess.csproj +++ b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchool.DataAccess.csproj @@ -37,5 +37,5 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs index a8e777651f..c99f717212 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs @@ -1,12 +1,18 @@ using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using OutOfSchool.Services.Enums; using OutOfSchool.Services.Extensions; using OutOfSchool.Services.Models; namespace OutOfSchool.Services { - public class OutOfSchoolDbContext : IdentityDbContext, IDataProtectionKeyContext + public class OutOfSchoolDbContext : IdentityDbContext, IDataProtectionKeyContext, IUnitOfWork { public OutOfSchoolDbContext(DbContextOptions options) : base(options) @@ -47,6 +53,12 @@ public OutOfSchoolDbContext(DbContextOptions options) public DbSet Favorites { get; set; } + public DbSet DateTimeRanges { get; set; } + + public async Task CompleteAsync() => await this.SaveChangesAsync(); + + public int Complete() => this.SaveChanges(); + protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); @@ -67,16 +79,16 @@ protected override void OnModelCreating(ModelBuilder builder) .HasMany(r => r.Users) .WithMany(u => u.ChatRooms) .UsingEntity( - j => j - .HasOne(cru => cru.User) - .WithMany(u => u.ChatRoomUsers) - .HasForeignKey(cru => cru.UserId) - .OnDelete(DeleteBehavior.Cascade), - j => j - .HasOne(cru => cru.ChatRoom) - .WithMany(r => r.ChatRoomUsers) - .HasForeignKey(cru => cru.ChatRoomId) - .OnDelete(DeleteBehavior.Cascade)); + j => j + .HasOne(cru => cru.User) + .WithMany(u => u.ChatRoomUsers) + .HasForeignKey(cru => cru.UserId) + .OnDelete(DeleteBehavior.Cascade), + j => j + .HasOne(cru => cru.ChatRoom) + .WithMany(r => r.ChatRoomUsers) + .HasForeignKey(cru => cru.ChatRoomId) + .OnDelete(DeleteBehavior.Cascade)); builder.Entity() .HasOne(r => r.Workshop) @@ -107,6 +119,18 @@ protected override void OnModelCreating(ModelBuilder builder) .HasForeignKey(x => x.ActualAddressId) .IsRequired(false); + builder.Entity() + .HasCheckConstraint("CK_DateTimeRanges_EndTimeIsAfterStartTime", "[EndTime] >= [StartTime]"); + + builder.Entity() + .Property(range => range.Workdays) + .HasConversion( + list => (byte)list.Aggregate((prev, next) => prev | next), + mask => + Enum.GetValues(typeof(DaysBitMask)).Cast().ToList() + .Where(amenity => amenity != 0 && ((DaysBitMask) mask).HasFlag(amenity)).ToList(), + ValueComparer.CreateDefault(typeof(List), true)); + builder.Seed(); builder.UpdateIdentityTables(); } diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/IWorkshopRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/IWorkshopRepository.cs index 299faa4366..d8241f595d 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/IWorkshopRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/IWorkshopRepository.cs @@ -8,11 +8,15 @@ namespace OutOfSchool.Services.Repository { public interface IWorkshopRepository : IEntityRepository { + IUnitOfWork UnitOfWork { get; } + /// /// Checks entity classId existence. /// /// Class id. /// True if Class exists, otherwise false. bool ClassExists(long id); + + Task GetWithNavigations(long id); } -} +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs index 997541f1f0..ab86117fda 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using OutOfSchool.Services.Models; @@ -13,11 +10,13 @@ public class WorkshopRepository : EntityRepository, IWorkshopRepositor private readonly OutOfSchoolDbContext db; public WorkshopRepository(OutOfSchoolDbContext dbContext) - : base(dbContext) + : base(dbContext) { db = dbContext; } + public IUnitOfWork UnitOfWork => db; + /// public new async Task Delete(Workshop entity) { @@ -43,6 +42,15 @@ public WorkshopRepository(OutOfSchoolDbContext dbContext) await db.SaveChangesAsync(); } + public async Task GetWithNavigations(long id) + { + return await db.Workshops + .Include(ws => ws.Address) + .Include(ws => ws.Teachers) + .Include(ws => ws.DateTimeRanges) + .SingleOrDefaultAsync(ws => ws.Id == id); + } + /// public bool ClassExists(long id) => db.Classes.Any(x => x.Id == id); } diff --git a/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.Designer.cs b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.Designer.cs new file mode 100644 index 0000000000..150c1f59c9 --- /dev/null +++ b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.Designer.cs @@ -0,0 +1,1304 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using OutOfSchool.Services; + +namespace OutOfSchool.IdentityServer.Data.Migrations.OutOfSchoolMigrations +{ + [DbContext(typeof(OutOfSchoolDbContext))] + [Migration("20210927144537_TimeRanges")] + partial class TimeRanges + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("FriendlyName") + .HasColumnType("nvarchar(max)"); + + b.Property("Xml") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(36) + .IsUnicode(false) + .HasColumnType("char(36)") + .IsFixedLength(true); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("BuildingNumber") + .IsRequired() + .HasMaxLength(15) + .HasColumnType("nvarchar(15)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("District") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Latitude") + .HasColumnType("float"); + + b.Property("Longitude") + .HasColumnType("float"); + + b.Property("Region") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Street") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.HasKey("Id"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Application", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("ChildId") + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetimeoffset"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ChildId"); + + b.HasIndex("ParentId"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Applications"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("ChatRoomId") + .HasColumnType("bigint"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("ChatRoomId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("WorkshopId"); + + b.ToTable("ChatRooms"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatRoomUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("ChatRoomId") + .HasColumnType("bigint"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("ChatRoomId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatRoomUsers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Child", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("DateOfBirth") + .HasColumnType("date"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("Gender") + .HasColumnType("int"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("MiddleName") + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("PlaceOfStudy") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("SocialGroupId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.HasIndex("SocialGroupId"); + + b.ToTable("Children"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.City", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("District") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Latitude") + .HasColumnType("float"); + + b.Property("Longitude") + .HasColumnType("float"); + + b.Property("Name") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Region") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.HasKey("Id"); + + b.ToTable("Cities"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Class", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("DepartmentId") + .HasColumnType("bigint"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Classes"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("EndTime") + .HasColumnType("time"); + + b.Property("StartTime") + .HasColumnType("time"); + + b.Property("Workdays") + .HasColumnType("tinyint"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("WorkshopId"); + + b.ToTable("DateTimeRanges"); + + b.HasCheckConstraint("CK_DateTimeRanges_EndTimeIsAfterStartTime", "[EndTime] >= [StartTime]"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("DirectionId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("DirectionId"); + + b.ToTable("Departments"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Direction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Directions"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Favorite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Favorites"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Parents"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Provider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("ActualAddressId") + .HasColumnType("bigint"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Director") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DirectorDateOfBirth") + .HasColumnType("date"); + + b.Property("EdrpouIpn") + .IsRequired() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Facebook") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Founder") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("FullTitle") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Instagram") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LegalAddressId") + .HasColumnType("bigint"); + + b.Property("Ownership") + .HasColumnType("int"); + + b.Property("PhoneNumber") + .HasMaxLength(15) + .HasColumnType("nvarchar(15)"); + + b.Property("ShortTitle") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Status") + .HasColumnType("bit"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Website") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("ActualAddressId"); + + b.HasIndex("LegalAddressId"); + + b.HasIndex("UserId"); + + b.ToTable("Providers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("CreationTime") + .HasColumnType("datetimeoffset"); + + b.Property("EntityId") + .HasColumnType("bigint"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Rate") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SocialGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("SocialGroups"); + + b.HasData( + new + { + Id = 1L, + Name = "Діти із багатодітних сімей" + }, + new + { + Id = 2L, + Name = "Діти із малозабезпечених сімей" + }, + new + { + Id = 3L, + Name = "Діти з інвалідністю" + }, + new + { + Id = 4L, + Name = "Діти-сироти" + }, + new + { + Id = 5L, + Name = "Діти, позбавлені батьківського піклування" + }); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Teacher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("DateOfBirth") + .HasColumnType("date"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Image") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("WorkshopId"); + + b.ToTable("Teachers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(36) + .IsUnicode(false) + .HasColumnType("char(36)") + .IsFixedLength(true); + + b.Property("CreatingTime") + .HasColumnType("datetimeoffset"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("IsRegistered") + .HasColumnType("bit"); + + b.Property("LastLogin") + .HasColumnType("datetimeoffset"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("MiddleName") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(84) + .IsUnicode(false) + .HasColumnType("char(84)") + .IsFixedLength(true); + + b.Property("PhoneNumber") + .HasMaxLength(15) + .IsUnicode(false) + .HasColumnType("varchar(15)") + .IsFixedLength(false); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("Role") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(36) + .IsUnicode(false) + .HasColumnType("varchar(36)") + .IsFixedLength(false); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("AddressId") + .HasColumnType("bigint"); + + b.Property("ClassId") + .HasColumnType("bigint"); + + b.Property("DepartmentId") + .HasColumnType("bigint"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("DirectionId") + .HasColumnType("bigint"); + + b.Property("DisabilityOptionsDesc") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Facebook") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Head") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("HeadDateOfBirth") + .HasColumnType("date"); + + b.Property("Instagram") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("IsPerMonth") + .HasColumnType("bit"); + + b.Property("Keywords") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Logo") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("MaxAge") + .HasColumnType("int"); + + b.Property("MinAge") + .HasColumnType("int"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(15) + .HasColumnType("nvarchar(15)"); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.Property("ProviderId") + .HasColumnType("bigint"); + + b.Property("ProviderTitle") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("WithDisabilityOptions") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("ClassId"); + + b.HasIndex("DirectionId"); + + b.HasIndex("ProviderId"); + + b.ToTable("Workshops"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("OutOfSchool.Services.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Application", b => + { + b.HasOne("OutOfSchool.Services.Models.Child", "Child") + .WithMany() + .HasForeignKey("ChildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany() + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("Applications") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Child"); + + b.Navigation("Parent"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatMessage", b => + { + b.HasOne("OutOfSchool.Services.Models.ChatRoom", "ChatRoom") + .WithMany("ChatMessages") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany("ChatMessages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChatRoom"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatRoom", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("ChatRooms") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatRoomUser", b => + { + b.HasOne("OutOfSchool.Services.Models.ChatRoom", "ChatRoom") + .WithMany("ChatRoomUsers") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany("ChatRoomUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChatRoom"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Child", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.SocialGroup", "SocialGroup") + .WithMany("Children") + .HasForeignKey("SocialGroupId"); + + b.Navigation("Parent"); + + b.Navigation("SocialGroup"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Class", b => + { + b.HasOne("OutOfSchool.Services.Models.Department", "Department") + .WithMany("Classes") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", null) + .WithMany("DateTimeRanges") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Department", b => + { + b.HasOne("OutOfSchool.Services.Models.Direction", "Direction") + .WithMany("Departments") + .HasForeignKey("DirectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Direction"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Favorite", b => + { + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany() + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Provider", b => + { + b.HasOne("OutOfSchool.Services.Models.Address", "ActualAddress") + .WithMany() + .HasForeignKey("ActualAddressId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("OutOfSchool.Services.Models.Address", "LegalAddress") + .WithMany() + .HasForeignKey("LegalAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ActualAddress"); + + b.Navigation("LegalAddress"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Rating", b => + { + b.HasOne("OutOfSchool.Services.Models.Parent", "Parent") + .WithMany() + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Teacher", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", "Workshop") + .WithMany("Teachers") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workshop"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.HasOne("OutOfSchool.Services.Models.Address", "Address") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Class", "Class") + .WithMany() + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Direction", "Direction") + .WithMany() + .HasForeignKey("DirectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OutOfSchool.Services.Models.Provider", "Provider") + .WithMany("Workshops") + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("Class"); + + b.Navigation("Direction"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.ChatRoom", b => + { + b.Navigation("ChatMessages"); + + b.Navigation("ChatRoomUsers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Department", b => + { + b.Navigation("Classes"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Direction", b => + { + b.Navigation("Departments"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Parent", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Provider", b => + { + b.Navigation("Workshops"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.SocialGroup", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.User", b => + { + b.Navigation("ChatMessages"); + + b.Navigation("ChatRoomUsers"); + }); + + modelBuilder.Entity("OutOfSchool.Services.Models.Workshop", b => + { + b.Navigation("Applications"); + + b.Navigation("ChatRooms"); + + b.Navigation("DateTimeRanges"); + + b.Navigation("Teachers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.cs b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.cs new file mode 100644 index 0000000000..137b49c1cf --- /dev/null +++ b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/20210927144537_TimeRanges.cs @@ -0,0 +1,56 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace OutOfSchool.IdentityServer.Data.Migrations.OutOfSchoolMigrations +{ + public partial class TimeRanges : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DaysPerWeek", + table: "Workshops"); + + migrationBuilder.CreateTable( + name: "DateTimeRanges", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + StartTime = table.Column(type: "time", nullable: false), + EndTime = table.Column(type: "time", nullable: false), + WorkshopId = table.Column(type: "bigint", nullable: false), + Workdays = table.Column(type: "tinyint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DateTimeRanges", x => x.Id); + table.CheckConstraint("CK_DateTimeRanges_EndTimeIsAfterStartTime", "[EndTime] >= [StartTime]"); + table.ForeignKey( + name: "FK_DateTimeRanges_Workshops_WorkshopId", + column: x => x.WorkshopId, + principalTable: "Workshops", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_DateTimeRanges_WorkshopId", + table: "DateTimeRanges", + column: "WorkshopId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DateTimeRanges"); + + migrationBuilder.AddColumn( + name: "DaysPerWeek", + table: "Workshops", + type: "int", + nullable: false, + defaultValue: 0); + } + } +} diff --git a/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs index 3c01f9f2cb..9430b4d89a 100644 --- a/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs +++ b/OutOfSchool/OutOfSchool.IdentityServer/Data/Migrations/OutOfSchoolMigrations/OutOfSchoolDbContextModelSnapshot.cs @@ -424,6 +424,34 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Classes"); }); + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("EndTime") + .HasColumnType("time"); + + b.Property("StartTime") + .HasColumnType("time"); + + b.Property("Workdays") + .HasColumnType("tinyint"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("WorkshopId"); + + b.ToTable("DateTimeRanges"); + + b.HasCheckConstraint("CK_DateTimeRanges_EndTimeIsAfterStartTime", "[EndTime] >= [StartTime]"); + }); + modelBuilder.Entity("OutOfSchool.Services.Models.Department", b => { b.Property("Id") @@ -837,9 +865,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("ClassId") .HasColumnType("bigint"); - b.Property("DaysPerWeek") - .HasColumnType("int"); - b.Property("DepartmentId") .HasColumnType("bigint"); @@ -1089,6 +1114,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Department"); }); + modelBuilder.Entity("OutOfSchool.Services.Models.DateTimeRange", b => + { + b.HasOne("OutOfSchool.Services.Models.Workshop", null) + .WithMany("DateTimeRanges") + .HasForeignKey("WorkshopId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("OutOfSchool.Services.Models.Department", b => { b.HasOne("OutOfSchool.Services.Models.Direction", "Direction") @@ -1258,6 +1292,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ChatRooms"); + b.Navigation("DateTimeRanges"); + b.Navigation("Teachers"); }); #pragma warning restore 612, 618 diff --git a/OutOfSchool/OutOfSchool.IdentityServer/appsettings.json b/OutOfSchool/OutOfSchool.IdentityServer/appsettings.json index 8b17ce99f1..354aa622b3 100644 --- a/OutOfSchool/OutOfSchool.IdentityServer/appsettings.json +++ b/OutOfSchool/OutOfSchool.IdentityServer/appsettings.json @@ -38,10 +38,12 @@ { "ClientId": "Swagger", "RedirectUris": [ - "http://localhost:5000/swagger/oauth2-redirect.html" + "http://localhost:5000/swagger/oauth2-redirect.html", + "https://localhost:5001/swagger/oauth2-redirect.html" ], "PostLogoutRedirectUris": [ - "http://localhost:5000/swagger/oauth2-redirect.html" + "http://localhost:5000/swagger/oauth2-redirect.html", + "https://localhost:5001/swagger/oauth2-redirect.html" ], "AllowedCorsOrigins": [ "http://localhost:5000" diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ParentControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ParentControllerTests.cs index af29435c8f..064e1d477a 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ParentControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/ParentControllerTests.cs @@ -110,7 +110,6 @@ public WorkshopDTO FakeWorkshop() Description = "Desc6", Price = 6000, WithDisabilityOptions = true, - DaysPerWeek = 6, Head = "Head6", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs index 9fd87debf3..0d6b902b42 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Controllers/WorkshopControllerTests.cs @@ -404,7 +404,6 @@ private WorkshopDTO FakeWorkshop() Description = "Desc6", Price = 6000, WithDisabilityOptions = true, - DaysPerWeek = 6, Head = "Head6", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -472,7 +471,6 @@ private List FakeWorkshops() Description = "Desc1", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 1, @@ -501,7 +499,6 @@ private List FakeWorkshops() Description = "Desc2", Price = 2000, WithDisabilityOptions = true, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 1, @@ -530,7 +527,6 @@ private List FakeWorkshops() Description = "Desc3", Price = 3000, WithDisabilityOptions = true, - DaysPerWeek = 3, Head = "Head3", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, @@ -555,7 +551,6 @@ private List FakeWorkshops() Description = "Desc4", Price = 4000, WithDisabilityOptions = true, - DaysPerWeek = 4, Head = "Head4", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, @@ -580,7 +575,6 @@ private List FakeWorkshops() Description = "Desc5", Price = 5000, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/ElasticSearchMappingExtensionsTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/ElasticSearchMappingExtensionsTests.cs index dd37cef3d7..accfaa7f2e 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/ElasticSearchMappingExtensionsTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/ElasticSearchMappingExtensionsTests.cs @@ -23,7 +23,6 @@ public void Mapping_WorkshopDto_ToESModel_IsCorrect() Price = 5000, IsPerMonth = true, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/MappingExtensionsTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/MappingExtensionsTests.cs index f2cc494a56..1bc27c04c9 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/MappingExtensionsTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Extensions/MappingExtensionsTests.cs @@ -267,7 +267,6 @@ public void Mapping_WorkshopDTO_ToCardDto_IsCorrect() Price = 5000, IsPerMonth = true, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceTests.cs index 280a6a27a0..86a02cc43b 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using AutoMapper; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; @@ -33,6 +34,7 @@ public class WorkshopServiceTests private Mock ratingServiceMoq; private Mock> loggerMoq; + private Mock mapperMoq; private Workshop newWorkshop; private Class classEntity; @@ -55,6 +57,7 @@ public void SetUp() ratingServiceMoq = new Mock(); loggerMoq = new Mock>(); + mapperMoq = new Mock(); workshopService = new WorkshopService( workshopRepository, @@ -62,7 +65,8 @@ public void SetUp() teacherRepository, addressRepository, ratingServiceMoq.Object, - loggerMoq.Object); + loggerMoq.Object, + mapperMoq.Object); SeedDatabase(); } @@ -225,7 +229,6 @@ public async Task Update_WhenEntityIsValid_ShouldUpdateAllRelationalEntities() Description = "Desc1", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -653,7 +656,6 @@ private void SeedDatabase() Description = "Desc", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -738,7 +740,6 @@ private void SeedDatabase() Keywords = "шаффл", Price = 0, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", @@ -801,7 +802,6 @@ private void SeedDatabase() Keywords = "танці¤діти¤шаффл", Price = 50, WithDisabilityOptions = false, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", @@ -863,7 +863,6 @@ private void SeedDatabase() Keywords = "м'яч¤біг¤ноги¤діти¤дорослі¤спорт", Price = 100, WithDisabilityOptions = true, - DaysPerWeek = 3, Head = "Head3", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -924,7 +923,6 @@ private void SeedDatabase() Keywords = "м'яч¤біг¤спорт", Price = 1000, WithDisabilityOptions = false, - DaysPerWeek = 4, Head = "Head4", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -986,7 +984,6 @@ private void SeedDatabase() Keywords = "рукоділля¤вишивка", Price = 0, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceUnitTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceUnitTests.cs index 8ddb364aac..d7f8c19c8a 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceUnitTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Database/WorkshopServiceUnitTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using AutoMapper; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -26,6 +27,7 @@ public class WorkshopServiceUnitTests private Mock ratingService; private Mock> logger; + private Mock mapperMoq; private Workshop newWorkshop; private List workshops; @@ -40,6 +42,7 @@ public void SetUp() addressRepositoryMoq = new Mock>(); ratingService = new Mock(); logger = new Mock>(); + mapperMoq = new Mock(); workshopService = new WorkshopService( workshopRepositoryMoq.Object, @@ -47,7 +50,8 @@ public void SetUp() teacherRepositoryMoq.Object, addressRepositoryMoq.Object, ratingService.Object, - logger.Object); + logger.Object, + mapperMoq.Object); FakeEntities(); } @@ -179,7 +183,6 @@ public async Task Update_WhenEntityIsValid_ShouldRunInTransaction() Description = "Desc1", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -312,7 +315,6 @@ private void FakeEntities() Description = "Desc", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -373,7 +375,6 @@ private void FakeEntities() Description = "Desc1", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -435,7 +436,6 @@ private void FakeEntities() Description = "Desc2", Price = 2000, WithDisabilityOptions = true, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -496,7 +496,6 @@ private void FakeEntities() Description = "Desc3", Price = 3000, WithDisabilityOptions = true, - DaysPerWeek = 3, Head = "Head3", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -556,7 +555,6 @@ private void FakeEntities() Description = "Desc4", Price = 4000, WithDisabilityOptions = true, - DaysPerWeek = 4, Head = "Head4", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -617,7 +615,6 @@ private void FakeEntities() Description = "Desc5", Price = 5000, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Elasticsearch/ESWorkshopServiceTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Elasticsearch/ESWorkshopServiceTests.cs index 899682e8b8..e66d8759bb 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Elasticsearch/ESWorkshopServiceTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/Elasticsearch/ESWorkshopServiceTests.cs @@ -219,7 +219,6 @@ public async Task ReIndex_WhenDocsWereUpdated_ShouldReturnTrue() Keywords = new List { "шаффл" }, Price = 0, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", @@ -282,7 +281,6 @@ public async Task ReIndex_WhenDocsWereUpdated_ShouldReturnTrue() Keywords = new List { "танці", "діти", "шаффл" }, Price = 50, WithDisabilityOptions = false, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", @@ -367,7 +365,6 @@ public async Task ReIndex_WhenDocsWereNotUpdated_ShouldReturnFalse() Keywords = new List { "шаффл" }, Price = 0, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", @@ -430,7 +427,6 @@ public async Task ReIndex_WhenDocsWereNotUpdated_ShouldReturnFalse() Keywords = new List { "танці", "діти", "шаффл" }, Price = 50, WithDisabilityOptions = false, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "Школа танцю", diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/WorkshopServicesCombinerTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/WorkshopServicesCombinerTests.cs index b5745f8efc..dfae2a7cb8 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/WorkshopServicesCombinerTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/WorkshopServicesCombinerTests.cs @@ -233,7 +233,6 @@ private WorkshopDTO FakeWorkshop() Description = "Desc6", Price = 6000, WithDisabilityOptions = true, - DaysPerWeek = 6, Head = "Head6", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderTitle = "ProviderTitle", @@ -312,7 +311,6 @@ private List FakeWorkshops() Description = "Desc1", Price = 1000, WithDisabilityOptions = true, - DaysPerWeek = 1, Head = "Head1", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 1, @@ -341,7 +339,6 @@ private List FakeWorkshops() Description = "Desc2", Price = 2000, WithDisabilityOptions = true, - DaysPerWeek = 2, Head = "Head2", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 1, @@ -370,7 +367,6 @@ private List FakeWorkshops() Description = "Desc3", Price = 3000, WithDisabilityOptions = true, - DaysPerWeek = 3, Head = "Head3", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, @@ -395,7 +391,6 @@ private List FakeWorkshops() Description = "Desc4", Price = 4000, WithDisabilityOptions = true, - DaysPerWeek = 4, Head = "Head4", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, @@ -420,7 +415,6 @@ private List FakeWorkshops() Description = "Desc5", Price = 5000, WithDisabilityOptions = true, - DaysPerWeek = 5, Head = "Head5", HeadDateOfBirth = new DateTime(1980, month: 12, 28), ProviderId = 2, diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs index 8f9d238f30..cdefdefe60 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/WorkshopController.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -6,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; +using OutOfSchool.Services.Enums; using OutOfSchool.WebApi.Config; using OutOfSchool.WebApi.Extensions; using OutOfSchool.WebApi.Models; diff --git a/OutOfSchool/OutOfSchool.WebApi/Models/ApplicationDTO.cs b/OutOfSchool/OutOfSchool.WebApi/Models/ApplicationDTO.cs index b012d2d5fe..b4decf90af 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Models/ApplicationDTO.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Models/ApplicationDTO.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -using System.Text.Json.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using OutOfSchool.Services.Enums; namespace OutOfSchool.WebApi.Models @@ -9,7 +10,7 @@ public class ApplicationDto { public long Id { get; set; } - [JsonConverter(typeof(JsonStringEnumConverter))] + [JsonConverter(typeof(StringEnumConverter))] public ApplicationStatus Status { get; set; } = ApplicationStatus.Pending; public DateTimeOffset CreationTime { get; set; } diff --git a/OutOfSchool/OutOfSchool.WebApi/Models/DateTimeRangeDto.cs b/OutOfSchool/OutOfSchool.WebApi/Models/DateTimeRangeDto.cs new file mode 100644 index 0000000000..406f95bf2d --- /dev/null +++ b/OutOfSchool/OutOfSchool.WebApi/Models/DateTimeRangeDto.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using OutOfSchool.Services.Enums; + +namespace OutOfSchool.WebApi.Models +{ + public class DateTimeRangeDto + { + public long Id { get; set; } + + public TimeSpan StartTime { get; set; } + + public TimeSpan EndTime { get; set; } + + public List Workdays { get; set; } + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Models/WorkshopDTO.cs b/OutOfSchool/OutOfSchool.WebApi/Models/WorkshopDTO.cs index 80a7c4e0a9..cdebd737cc 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Models/WorkshopDTO.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Models/WorkshopDTO.cs @@ -2,10 +2,13 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using Castle.Core.Internal; +using OutOfSchool.Services.Enums; namespace OutOfSchool.WebApi.Models { - public class WorkshopDTO + public class WorkshopDTO : IValidatableObject { public long Id { get; set; } @@ -46,10 +49,6 @@ public class WorkshopDTO [Range(0, 18, ErrorMessage = "Max age should be a number from 0 to 18")] public int MaxAge { get; set; } - [Required(ErrorMessage = "Specify how many times per week lessons will be held")] - [Range(1, 7, ErrorMessage = "Field should be a digit from 1 to 7")] - public int DaysPerWeek { get; set; } - [Column(TypeName = "decimal(18,2)")] [Range(0, 10000, ErrorMessage = "Field value should be in a range from 1 to 10 000")] public decimal Price { get; set; } = default; @@ -107,5 +106,34 @@ public class WorkshopDTO public AddressDto Address { get; set; } public IEnumerable Teachers { get; set; } + + [Required] + public List DateTimeRanges { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + // TODO: Validate DateTimeRanges are not empty when frontend is ready + foreach (var dateTimeRange in DateTimeRanges) + { + if (dateTimeRange.StartTime > dateTimeRange.EndTime) + { + yield return new ValidationResult( + "End date can't be earlier that start date"); + } + + if (dateTimeRange.Workdays.IsNullOrEmpty() || dateTimeRange.Workdays.Any(workday => workday == DaysBitMask.None)) + { + yield return new ValidationResult( + "Workdays are required"); + } + + var daysHs = new HashSet(); + if (!dateTimeRange.Workdays.All(daysHs.Add)) + { + yield return new ValidationResult( + "Workdays contain duplications"); + } + } + } } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/OutOfSchool.WebApi.csproj b/OutOfSchool/OutOfSchool.WebApi/OutOfSchool.WebApi.csproj index 9a2c90f4be..64dff2ed98 100644 --- a/OutOfSchool/OutOfSchool.WebApi/OutOfSchool.WebApi.csproj +++ b/OutOfSchool/OutOfSchool.WebApi/OutOfSchool.WebApi.csproj @@ -14,6 +14,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs index 138f1f4783..4770dae118 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs @@ -3,8 +3,10 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using AutoMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using OutOfSchool.Services.Enums; using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository; @@ -26,6 +28,7 @@ public class WorkshopService : IWorkshopService private readonly IEntityRepository
addressRepository; private readonly IRatingService ratingService; private readonly ILogger logger; + private readonly IMapper mapper; /// /// Initializes a new instance of the class. @@ -36,13 +39,15 @@ public class WorkshopService : IWorkshopService /// Repository for Address. /// Rating service. /// Logger. + /// Automapper DI service. public WorkshopService( IWorkshopRepository workshopRepository, IClassRepository classRepository, IEntityRepository teacherRepository, IEntityRepository
addressRepository, IRatingService ratingService, - ILogger logger) + ILogger logger, + IMapper mapper) { this.workshopRepository = workshopRepository; this.classRepository = classRepository; @@ -50,6 +55,7 @@ public WorkshopService( this.addressRepository = addressRepository; this.ratingService = ratingService; this.logger = logger; + this.mapper = mapper; } /// @@ -63,13 +69,14 @@ public async Task Create(WorkshopDTO dto) // In case if DirectionId and DepartmentId does not match ClassId await this.FillDirectionsFields(dto).ConfigureAwait(false); - Func> operation = async () => await workshopRepository.Create(dto.ToDomain()).ConfigureAwait(false); + Func> operation = async () => + await workshopRepository.Create(mapper.Map(dto)).ConfigureAwait(false); var newWorkshop = await workshopRepository.RunInTransaction(operation).ConfigureAwait(false); logger.LogInformation($"Workshop with Id = {newWorkshop?.Id} created successfully."); - return newWorkshop.ToModel(); + return mapper.Map(newWorkshop); } /// @@ -77,21 +84,19 @@ public async Task> GetAll(OffsetFilter offsetFilter) { logger.LogInformation("Getting all Workshops started."); - if (offsetFilter is null) - { - offsetFilter = new OffsetFilter(); - } + offsetFilter ??= new OffsetFilter(); var count = await workshopRepository.Count().ConfigureAwait(false); - var workshops = workshopRepository.Get(skip: offsetFilter.From, take: offsetFilter.Size, orderBy: x => x.Id, ascending: true).ToList(); + var workshops = workshopRepository.Get(skip: offsetFilter.From, take: offsetFilter.Size, + orderBy: x => x.Id, ascending: true).ToList(); logger.LogInformation(!workshops.Any() ? "Workshop table is empty." : $"All {workshops.Count} records were successfully received from the Workshop table"); - var workshopsDTO = workshops.Select(x => x.ToModel()).ToList(); + var workshopsDTO = mapper.Map>(workshops); var workshopsWithRating = GetWorkshopsWithAverageRating(workshopsDTO); - return new SearchResult() { TotalAmount = count, Entities = workshopsWithRating }; + return new SearchResult() {TotalAmount = count, Entities = workshopsWithRating}; } /// @@ -99,7 +104,7 @@ public async Task GetById(long id) { logger.LogInformation($"Getting Workshop by Id started. Looking Id = {id}."); - var workshop = await workshopRepository.GetById(id).ConfigureAwait(false); + var workshop = await workshopRepository.GetWithNavigations(id).ConfigureAwait(false); if (workshop == null) { @@ -108,7 +113,7 @@ public async Task GetById(long id) logger.LogInformation($"Successfully got a Workshop with Id = {id}."); - var workshopDTO = workshop.ToModel(); + var workshopDTO = mapper.Map(workshop); var rating = ratingService.GetAverageRating(workshopDTO.Id, RatingType.Workshop); @@ -129,7 +134,7 @@ public async Task> GetByProviderId(long id) ? $"There aren't Workshops for Provider with Id = {id}." : $"From Workshop table were successfully received {workshops.Count()} records."); - var workshopsDTO = workshops.Select(x => x.ToModel()).ToList(); + var workshopsDTO = mapper.Map>(workshops); return GetWorkshopsWithAverageRating(workshopsDTO); } @@ -141,73 +146,27 @@ public async Task Update(WorkshopDTO dto) { logger.LogInformation($"Updating Workshop with Id = {dto?.Id} started."); - var workshop = workshopRepository.GetByFilterNoTracking(x => x.Id == dto.Id, "Address,Teachers").FirstOrDefault(); + // In case if DirectionId and DepartmentId does not match ClassId + await this.FillDirectionsFields(dto).ConfigureAwait(false); - if (workshop is null) - { - throw new ArgumentOutOfRangeException($"The workshop with id:{dto.Id} was not found."); - } + var currentWorkshop = await workshopRepository.GetWithNavigations(dto!.Id).ConfigureAwait(false); + // In case if AddressId was changed. AddresId is one and unique for workshop. + dto.AddressId = currentWorkshop.AddressId; + dto.Address.Id = currentWorkshop.AddressId; + + mapper.Map(dto, currentWorkshop); try { - // In case if DirectionId and DepartmentId does not match ClassId - await this.FillDirectionsFields(dto).ConfigureAwait(false); - - // In case if AddressId was changed. AddresId is one and unique for workshop. - dto.AddressId = workshop.AddressId; - dto.Address.Id = workshop.AddressId; - - // In case if WorkshopId of teachers was changed. - foreach (var teacher in dto.Teachers) - { - teacher.WorkshopId = workshop.Id; - } - - this.CompareTwoListsOfTeachers( - dto.Teachers, - workshop.Teachers, - out List teachersToCreate, - out List teachersToUpdate, - out List teachersToDelete); - - // When updating entity Workshop with the existing list - // EF Core adds created and updated entities to the list so - // when we return updated entity duplication happens. - // This is only for returning entity. Database will be updated correctly. - dto.Teachers = null; - - Func> updateWorkshop = async () => - { - foreach (var teacherDto in teachersToCreate) - { - await teacherRepository.Create(teacherDto.ToDomain()).ConfigureAwait(false); - } - - foreach (var teacherDto in teachersToUpdate) - { - await teacherRepository.Update(teacherDto.ToDomain()).ConfigureAwait(false); - } - - foreach (var teacherDto in teachersToDelete) - { - await teacherRepository.Delete(teacherDto.ToDomain()).ConfigureAwait(false); - } - - await addressRepository.Update(dto.Address.ToDomain()).ConfigureAwait(false); - return await workshopRepository.Update(dto.ToDomain()).ConfigureAwait(false); - }; - - var newWorkshop = await workshopRepository.RunInTransaction(updateWorkshop).ConfigureAwait(false); - - logger.LogInformation($"Workshop with Id = {workshop?.Id} updated succesfully."); - - return newWorkshop.ToModel(); + await workshopRepository.UnitOfWork.CompleteAsync().ConfigureAwait(false); } catch (DbUpdateConcurrencyException exception) { logger.LogError($"Updating failed. Exception: {exception.Message}"); throw; } + + return mapper.Map(currentWorkshop); } /// @@ -221,14 +180,7 @@ public async Task Delete(long id) try { - Func> deleteWorkshop = async () => - { - await workshopRepository.Delete(entity).ConfigureAwait(false); - return new Workshop() { Id = default }; - }; - - await workshopRepository.RunInTransaction(deleteWorkshop).ConfigureAwait(false); - + await workshopRepository.Delete(entity).ConfigureAwait(false); logger.LogInformation($"Workshop with Id = {id} succesfully deleted."); } catch (DbUpdateConcurrencyException) @@ -252,13 +204,14 @@ public async Task> GetByFilter(WorkshopFilter filter = var orderBy = GetOrderParameter(filter); var workshopsCount = await workshopRepository.Count(where: filterPredicate).ConfigureAwait(false); - var workshops = workshopRepository.Get(filter.From, filter.Size, string.Empty, filterPredicate, orderBy.Item1, orderBy.Item2).ToList(); + var workshops = workshopRepository.Get(filter.From, filter.Size, string.Empty, filterPredicate, + orderBy.Item1, orderBy.Item2).ToList(); logger.LogInformation(!workshops.Any() ? "There was no matching entity found." : $"All matching {workshops.Count} records were successfully received from the Workshop table"); - var workshopsDTO = workshops.Select(x => x.ToModel()).ToList(); + var workshopsDTO = mapper.Map>(workshops); var result = new SearchResult() { @@ -312,7 +265,8 @@ private Expression> PredicateBuild(WorkshopFilter filter) } else if (filter.IsFree && !(filter.MinPrice == 0 && filter.MaxPrice == int.MaxValue)) { - predicate = predicate.And(x => (x.Price >= filter.MinPrice && x.Price <= filter.MaxPrice) || x.Price == 0); + predicate = predicate.And(x => + (x.Price >= filter.MinPrice && x.Price <= filter.MaxPrice) || x.Price == 0); } if (filter.MinAge != 0 || filter.MaxAge != 100) @@ -377,49 +331,10 @@ private async Task FillDirectionsFields(WorkshopDTO dto) dto.DirectionId = classEntity.Department.DirectionId; } - private void CompareTwoListsOfTeachers( - IEnumerable source, - IEnumerable destination, - out List teachersToCreate, - out List teachersToUpdate, - out List teachersToDelete) - { - // Sort new teachers and old teachers - var oldTeachers = new List(); - teachersToCreate = new List(); - foreach (var teacherDto in source) - { - if (destination.Any(x => x.Id == teacherDto.Id)) - { - oldTeachers.Add(teacherDto); - } - else - { - // In case if TeacherId was set wrong, when someone is trying to hack the system. - teacherDto.Id = default; - teachersToCreate.Add(teacherDto); - } - } - - // Sort teachers for update and delete - teachersToUpdate = new List(); - teachersToDelete = new List(); - foreach (var teacher in destination) - { - if (oldTeachers.Any(x => x.Id == teacher.Id)) - { - teachersToUpdate.Add(oldTeachers.First(x => x.Id == teacher.Id)); - } - else - { - teachersToDelete.Add(teacher.ToModel()); - } - } - } - private List GetWorkshopsWithAverageRating(List workshopsDTOs) { - var averageRatings = ratingService.GetAverageRatingForRange(workshopsDTOs.Select(p => p.Id), RatingType.Workshop); + var averageRatings = + ratingService.GetAverageRatingForRange(workshopsDTOs.Select(p => p.Id), RatingType.Workshop); if (averageRatings != null) { diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index 21bff991b8..74e4f78df2 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -151,7 +151,7 @@ public async Task GetByUserId(string id) Expression> filter = p => p.UserId == id; - var providers = await providerRepository.GetByFilter(filter).ConfigureAwait(false); + var providers = (await providerRepository.GetByFilter(filter).ConfigureAwait(false)).ToList(); if (!providers.Any()) { diff --git a/OutOfSchool/OutOfSchool.WebApi/Startup.cs b/OutOfSchool/OutOfSchool.WebApi/Startup.cs index 9afcb210cb..5ce558ffae 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Startup.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Startup.cs @@ -24,6 +24,7 @@ using OutOfSchool.WebApi.Hubs; using OutOfSchool.WebApi.Middlewares; using OutOfSchool.WebApi.Services; +using OutOfSchool.WebApi.Util; using Serilog; namespace OutOfSchool.WebApi @@ -110,7 +111,7 @@ public void ConfigureServices(IServiceCollection services) .AllowAnyHeader() .AllowCredentials())); - services.AddControllers(); + services.AddControllers().AddNewtonsoftJson(); // TODO: Ask frontend if all enums as strings are fine by adding serializer project wide // .AddJsonOptions(options => @@ -181,7 +182,7 @@ public void ConfigureServices(IServiceCollection services) services.AddProxy(); - services.AddAutoMapper(typeof(Startup)); + services.AddAutoMapper(typeof(MappingProfile)); services.AddSignalR(); } diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/DateTimeRangeComparerWithoutFK.cs b/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/DateTimeRangeComparerWithoutFK.cs new file mode 100644 index 0000000000..22d7cfcb1b --- /dev/null +++ b/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/DateTimeRangeComparerWithoutFK.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using OutOfSchool.Services.Models; + +namespace OutOfSchool.WebApi.Util.CustomComparers +{ + public class DateTimeRangeComparerWithoutFK : IEqualityComparer + { + public bool Equals(DateTimeRange x, DateTimeRange y) + { + if (x == null && y == null) + return true; + if (x == null || y == null) + return false; + return x.Id == y.Id && x.StartTime.Equals(y.StartTime) && x.EndTime.Equals(y.EndTime) && x.Workdays.SequenceEqual(y.Workdays); + } + + public int GetHashCode(DateTimeRange obj) + { + var hash = default(HashCode); + hash.Add(obj.Id); + hash.Add(obj.StartTime); + hash.Add(obj.EndTime); + obj.Workdays.Sort(); + obj.Workdays.ForEach(wd => hash.Add(wd)); + return hash.ToHashCode(); + } + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/TeacherComparerWithoutFK.cs b/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/TeacherComparerWithoutFK.cs new file mode 100644 index 0000000000..d1463c46d2 --- /dev/null +++ b/OutOfSchool/OutOfSchool.WebApi/Util/CustomComparers/TeacherComparerWithoutFK.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using OutOfSchool.Services.Models; + +namespace OutOfSchool.WebApi.Util.CustomComparers +{ + public class TeacherComparerWithoutFK : IEqualityComparer + { + public bool Equals(Teacher x, Teacher y) + { + if (x == null && y == null) + return true; + if (x == null || y == null) + return false; + return x.Id == y.Id && x.FirstName == y.FirstName && x.LastName == y.LastName && x.MiddleName == y.MiddleName && x.DateOfBirth == y.DateOfBirth && x.Description == y.Description && x.Image == y.Image; + } + + public int GetHashCode(Teacher obj) + { + return HashCode.Combine(obj.Id, obj.FirstName, obj.LastName, obj.MiddleName, obj.DateOfBirth, obj.Description, obj.Image); + } + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs new file mode 100644 index 0000000000..b4eeb7a72f --- /dev/null +++ b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using AutoMapper; +using OutOfSchool.Services.Models; +using OutOfSchool.WebApi.Models; +using OutOfSchool.WebApi.Util.CustomComparers; + +namespace OutOfSchool.WebApi.Util +{ + public class MappingProfile : Profile + { + public MappingProfile() + { + const char SEPARATOR = '¤'; + CreateMap() + .ForMember(dest => dest.Keywords, opt => opt.MapFrom(src => string.Join(SEPARATOR, src.Keywords.Distinct()))) + .ForMember(dest => dest.Direction, opt => opt.Ignore()) + .ForMember(dest => dest.DateTimeRanges, opt => opt.MapFrom((dto, entity, dest, ctx) => + { + var dateTimeRanges = ctx.Mapper.Map>(dto.DateTimeRanges); + if (dest is { } && dest.Any()) + { + var dtoTimeRangesHs = + new HashSet(dateTimeRanges, new DateTimeRangeComparerWithoutFK()); + foreach (var destDateTimeRange in dest) + { + if (dtoTimeRangesHs.Remove(destDateTimeRange)) + { + dtoTimeRangesHs.Add(destDateTimeRange); + } + } + + return dtoTimeRangesHs.ToList(); + } + + return dateTimeRanges; + })) + .ForMember(dest => dest.Teachers, opt => opt.MapFrom((dto, entity, dest, ctx) => + { + var dtoTeachers = ctx.Mapper.Map>(dto.Teachers); + if (dest is { } && dest.Any()) + { + var dtoTeachersHs = new HashSet(dtoTeachers, new TeacherComparerWithoutFK()); + foreach (var destTeacher in dest.Where(destTeacher => dtoTeachersHs.Remove(destTeacher))) + { + dtoTeachersHs.Add(destTeacher); + } + + return dtoTeachersHs.ToList(); + } + + return dtoTeachers; + })) + ; + + CreateMap() + .ForMember( + dest => dest.Keywords, + opt => opt.MapFrom(src => src.Keywords.Split(SEPARATOR, StringSplitOptions.None))) + .ForMember(dest => dest.Direction, opt => opt.MapFrom(src => src.Direction.Title)); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + } + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 64b459aa84..28cdd121bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' +version: '3.4' services: # === SQL SERVER === sql-server: