diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..46b858b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,569 @@ +# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/language-rules + +[*.{cs,vb}] +tab_width = 4 +indent_size = 4 +end_of_line = crlf + +dotnet_diagnostic.ide0001.severity = warning +dotnet_diagnostic.ide0002.severity = warning + +# IDE0003 and IDE0009 +dotnet_diagnostic.sa0001.severity = none +dotnet_diagnostic.ide0003.severity = warning +dotnet_diagnostic.ide0009.severity = warning +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +dotnet_diagnostic.SA1010.severity = none + +dotnet_diagnostic.ide0004.severity = warning +dotnet_diagnostic.ide0005.severity = warning + +# IDE0007 and IDE0008 +dotnet_diagnostic.ide0007.severity = warning +dotnet_diagnostic.ide0008.severity = warning +csharp_style_var_when_type_is_apparent = true:warning +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_elsewhere = false:silent + +# IDE0010 +dotnet_diagnostic.ide0010.severity = suggestion + +# IDE0011 +dotnet_diagnostic.ide0011.severity = warning +csharp_prefer_braces = when_multiline:warning + +# IDE0016 +dotnet_diagnostic.ide0016.severity = warning +csharp_style_throw_expression = true:warning + +# IDE0017 +dotnet_diagnostic.ide0017.severity = suggestion +dotnet_style_object_initializer = true:suggestion + +# IDE0018 +dotnet_diagnostic.ide0018.severity = suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# IDE0019 +dotnet_diagnostic.ide0019.severity = warning +csharp_style_pattern_matching_over_as_with_null_check = true:warning + +# IDE0020 and IDE0038 +dotnet_diagnostic.ide0020.severity = warning +dotnet_diagnostic.ide0038.severity = warning +csharp_style_pattern_matching_over_is_with_cast_check = true:warning + +# IDE0021 +dotnet_diagnostic.ide0021.severity = warning +csharp_style_expression_bodied_constructors = false:warning + +# IDE0022 +dotnet_diagnostic.ide0022.severity = suggestion +csharp_style_expression_bodied_methods = false:suggestion + +# IDE0023 and IDE0024 +dotnet_diagnostic.ide0023.severity = suggestion +dotnet_diagnostic.ide0024.severity = suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion + +# IDE0025 +dotnet_diagnostic.ide0025.severity = warning +csharp_style_expression_bodied_properties = when_on_single_line:warning + +# IDE0026 +dotnet_diagnostic.ide0026.severity = suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion + +# IDE0027 +dotnet_diagnostic.ide0027.severity = suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +# IDE0028 +dotnet_diagnostic.ide0028.severity = suggestion +dotnet_style_collection_initializer = true:suggestion + +# IDE0029 and IDE0030 +dotnet_diagnostic.ide0029.severity = suggestion +dotnet_diagnostic.ide0030.severity = suggestion +dotnet_style_coalesce_expression = true:suggestion + +# IDE0031 +dotnet_diagnostic.ide0031.severity = suggestion +dotnet_style_null_propagation = true:suggestion + +# IDE0032 +dotnet_diagnostic.ide0032.severity = warning +dotnet_style_prefer_auto_properties = true:warning + +# IDE0033 +dotnet_diagnostic.ide0033.severity = warning +dotnet_style_explicit_tuple_names = true:warning + +# IDE0034 +dotnet_diagnostic.ide0034.severity = warning +csharp_prefer_simple_default_expression = true:warning + +# IDE0035 +dotnet_diagnostic.ide0035.severity = warning + +# IDE0036 +dotnet_diagnostic.ide0036.severity = warning +csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async + +# IDE0037 +dotnet_diagnostic.ide0037.severity = warning +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning + +# IDE0039 +dotnet_diagnostic.ide0039.severity = suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion + +# IDE0040 +dotnet_diagnostic.ide0040.severity = warning +dotnet_style_require_accessibility_modifiers = always:warning + +# IDE0041 +dotnet_diagnostic.ide0041.severity = warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning + +# IDE0042 +dotnet_diagnostic.ide0042.severity = suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion + +# IDE0044 +dotnet_diagnostic.ide0044.severity = warning +dotnet_style_readonly_field = true:warning + +# IDE0045 +dotnet_diagnostic.ide0045.severity = suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion + +# IDE0046 +dotnet_diagnostic.ide0046.severity = suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion + +# IDE0047 and IDE0048 +dotnet_diagnostic.ide0047.severity = warning +dotnet_diagnostic.ide0048.severity = warning +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning + +# IDE0049 +dotnet_diagnostic.ide0049.severity = warning +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning + +# IDE0050-52 +dotnet_diagnostic.ide0050.severity = warning +dotnet_diagnostic.ide0051.severity = warning +dotnet_diagnostic.ide0052.severity = warning + +# IDE0053 +dotnet_diagnostic.ide0053.severity = suggestion +csharp_style_expression_bodied_lambdas = true:suggestion + +# IDE0054 and IDE0074 +dotnet_diagnostic.ide0054.severity = suggestion +dotnet_diagnostic.ide0074.severity = suggestion +dotnet_style_prefer_compound_assignment = true:suggestion + +# IDE0055 +dotnet_sort_system_directives_first = false +dotnet_separate_import_directive_groups = false +dotnet_style_namespace_match_folder = true:warning +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = false +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = no_change +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true + +# IDE0056 +dotnet_diagnostic.ide0056.severity = warning +csharp_style_prefer_index_operator = false:warning + +# IDE0057 +dotnet_diagnostic.ide0057.severity = warning +csharp_style_prefer_range_operator = false:warning + +# IDE0058, IDE0059, IDE0060 +dotnet_diagnostic.ide0058.severity = none +dotnet_diagnostic.ide0059.severity = none +dotnet_diagnostic.ide0060.severity = none +csharp_style_unused_value_expression_statement_preference = discard_variable:none +csharp_style_unused_value_assignment_preference = discard_variable:none +dotnet_code_quality_unused_parameters = all:none + + +# IDE0061 +dotnet_diagnostic.ide0061.severity = suggestion +csharp_style_expression_bodied_local_functions = false:suggestion + +# IDE0062 +dotnet_diagnostic.ide0062.severity = suggestion +csharp_prefer_static_local_function = true:suggestion + +# IDE0063 +dotnet_diagnostic.ide0063.severity = warning +csharp_prefer_simple_using_statement = true:warning + +# IDE0064 +dotnet_diagnostic.ide0064.severity = warning +dotnet_diagnostic.ide0064.severity = none + +# IDE0065 +dotnet_diagnostic.ide0065.severity = warning +csharp_using_directive_placement = outside_namespace:warning + +# IDE0066 +dotnet_diagnostic.ide0066.severity = warning +csharp_style_prefer_switch_expression = true:warning + +# IDE0070 +dotnet_diagnostic.ide0070.severity = warning + +# IDE0071 +dotnet_diagnostic.ide0071.severity = none +dotnet_style_prefer_simplified_interpolation = true:suggestion + +# IDE0072 +dotnet_diagnostic.ide0072.severity = warning + +# IDE0073 +file_header_template = unset + +# IDE0075 +dotnet_diagnostic.ide0075.severity = suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion + +# IDE0078 +# dotnet_diagnostic.IDE0078.severity = warning +# csharp_style_prefer_pattern_matching = true:suggestion +csharp_style_prefer_pattern_matching = true:none + +# IDE0082 +dotnet_diagnostic.ide0082.severity = warning + +# IDE0083 +dotnet_diagnostic.ide0083.severity = warning +csharp_style_prefer_not_pattern = true:warning + +# IDE0090 +dotnet_diagnostic.ide0090.severity = warning +csharp_style_implicit_object_creation_when_type_is_apparent = false:warning + +# IDE0100 +dotnet_diagnostic.ide0100.severity = warning + +# IDE0110 +dotnet_diagnostic.ide0110.severity = warning + +# IDE0150 +dotnet_diagnostic.ide0150.severity = warning +csharp_style_prefer_null_check_over_type_check = false:warning + +# IDE0160 and IDE0161 +dotnet_diagnostic.ide0161.severity = warning +csharp_style_namespace_declarations = file_scoped:warning + +# IDE0170 +dotnet_diagnostic.ide0170.severity = none +csharp_style_prefer_extended_property_pattern = true:none + +# IDE0180 +dotnet_diagnostic.ide0180.severity = suggestion +csharp_style_prefer_tuple_swap = false:suggestion + +# IDE1005 +dotnet_diagnostic.ide1005.severity = suggestion +csharp_style_conditional_delegate_call = true:suggestion + +dotnet_diagnostic.ca1000.severity = none +dotnet_diagnostic.ca1001.severity = warning +dotnet_diagnostic.ca1002.severity = warning +dotnet_diagnostic.ca1003.severity = none +dotnet_diagnostic.ca1005.severity = none +dotnet_diagnostic.ca1008.severity = none +dotnet_diagnostic.ca1010.severity = warning +dotnet_diagnostic.ca1012.severity = warning +dotnet_diagnostic.ca1014.severity = none +dotnet_diagnostic.ca1016.severity = none +dotnet_diagnostic.ca1017.severity = none +dotnet_diagnostic.ca1018.severity = warning +dotnet_diagnostic.ca1019.severity = warning +dotnet_diagnostic.ca1021.severity = warning +dotnet_diagnostic.ca1024.severity = suggestion +dotnet_diagnostic.ca1027.severity = none +dotnet_diagnostic.ca1028.severity = warning +dotnet_diagnostic.ca1030.severity = none +dotnet_diagnostic.ca1031.severity = none +dotnet_diagnostic.ca1032.severity = none +dotnet_diagnostic.ca1033.severity = none +dotnet_diagnostic.ca1034.severity = none +dotnet_diagnostic.ca1036.severity = silent +dotnet_diagnostic.ca1040.severity = none +dotnet_diagnostic.ca1041.severity = suggestion +dotnet_diagnostic.ca1043.severity = none +dotnet_diagnostic.ca1044.severity = warning +dotnet_diagnostic.ca1045.severity = warning +dotnet_diagnostic.ca1046.severity = suggestion +dotnet_diagnostic.ca1047.severity = warning +dotnet_diagnostic.ca1050.severity = warning +dotnet_diagnostic.ca1051.severity = warning +dotnet_diagnostic.ca1052.severity = none +dotnet_diagnostic.ca1053.severity = none +dotnet_diagnostic.ca1054.severity = suggestion +dotnet_diagnostic.ca1055.severity = suggestion +dotnet_diagnostic.ca1056.severity = suggestion +dotnet_diagnostic.ca1058.severity = warning +dotnet_diagnostic.ca1060.severity = none +dotnet_diagnostic.ca1061.severity = warning +dotnet_diagnostic.ca1062.severity = none +dotnet_diagnostic.ca1063.severity = none +dotnet_diagnostic.ca1064.severity = warning +dotnet_diagnostic.ca1065.severity = warning +dotnet_diagnostic.ca1067.severity = warning +dotnet_diagnostic.ca1068.severity = suggestion +dotnet_diagnostic.ca1069.severity = warning +dotnet_diagnostic.ca1079.severity = warning +dotnet_diagnostic.ca1200.severity = none +dotnet_diagnostic.ca1303.severity = none +dotnet_diagnostic.ca1304.severity = none +dotnet_diagnostic.ca1305.severity = none +dotnet_diagnostic.ca1307.severity = warning +dotnet_diagnostic.ca1308.severity = suggestion +dotnet_diagnostic.ca1309.severity = suggestion +dotnet_diagnostic.ca1310.severity = suggestion +dotnet_diagnostic.ca1401.severity = warning +dotnet_diagnostic.ca1416.severity = warning +dotnet_diagnostic.ca1417.severity = warning +dotnet_diagnostic.ca1418.severity = warning +dotnet_diagnostic.ca1419.severity = warning +dotnet_diagnostic.ca1501.severity = warning +dotnet_diagnostic.ca1502.severity = warning +dotnet_diagnostic.ca1505.severity = warning +dotnet_diagnostic.ca1506.severity = warning +dotnet_diagnostic.ca1507.severity = suggestion +dotnet_diagnostic.ca1508.severity = warning +# dotnet_diagnostic.CA1509.severity = none +dotnet_diagnostic.ca1700.severity = none +dotnet_diagnostic.ca1707.severity = warning +dotnet_diagnostic.ca1708.severity = none +dotnet_diagnostic.ca1710.severity = none +dotnet_diagnostic.ca1711.severity = none +dotnet_diagnostic.ca1712.severity = none +dotnet_diagnostic.ca1713.severity = none +dotnet_diagnostic.ca1714.severity = suggestion +dotnet_diagnostic.ca1715.severity = warning +dotnet_diagnostic.ca1716.severity = warning +dotnet_diagnostic.ca1717.severity = none +dotnet_diagnostic.ca1720.severity = warning +dotnet_diagnostic.ca1721.severity = warning +dotnet_diagnostic.ca1724.severity = warning +dotnet_diagnostic.ca1725.severity = warning +dotnet_diagnostic.ca1727.severity = none +dotnet_diagnostic.ca1801.severity = warning +dotnet_diagnostic.ca1802.severity = warning +dotnet_diagnostic.ca1805.severity = none +dotnet_diagnostic.ca1806.severity = none +dotnet_diagnostic.ca1810.severity = none +dotnet_diagnostic.ca1812.severity = none +# dotnet_diagnostic.CA1812.severity = warning +dotnet_diagnostic.ca1813.severity = warning +dotnet_diagnostic.ca1814.severity = warning +dotnet_diagnostic.ca1815.severity = suggestion +dotnet_diagnostic.ca1816.severity = none +dotnet_diagnostic.ca1819.severity = none +dotnet_diagnostic.ca1820.severity = warning +dotnet_diagnostic.ca1821.severity = warning +dotnet_diagnostic.ca1822.severity = none +dotnet_diagnostic.ca1823.severity = warning +dotnet_diagnostic.ca1824.severity = none +dotnet_diagnostic.ca1825.severity = warning +dotnet_diagnostic.ca1826.severity = none +dotnet_diagnostic.ca1827.severity = warning +dotnet_diagnostic.ca1828.severity = warning +dotnet_diagnostic.ca1829.severity = warning +dotnet_diagnostic.ca1830.severity = suggestion +dotnet_diagnostic.ca1831.severity = suggestion +dotnet_diagnostic.ca1832.severity = suggestion +dotnet_diagnostic.ca1833.severity = suggestion +dotnet_diagnostic.ca1834.severity = suggestion +dotnet_diagnostic.ca1835.severity = suggestion +dotnet_diagnostic.ca1836.severity = warning +dotnet_diagnostic.ca1837.severity = warning +dotnet_diagnostic.ca1838.severity = warning +dotnet_diagnostic.ca1841.severity = none +dotnet_diagnostic.ca1842.severity = none +dotnet_diagnostic.ca1843.severity = none +dotnet_diagnostic.ca1844.severity = warning +dotnet_diagnostic.ca1845.severity = suggestion +dotnet_diagnostic.ca1846.severity = suggestion +dotnet_diagnostic.ca1847.severity = suggestion +dotnet_diagnostic.ca1848.severity = none +dotnet_diagnostic.ca1849.severity = suggestion +dotnet_diagnostic.ca1850.severity = suggestion +dotnet_diagnostic.ca1851.severity = warning +dotnet_diagnostic.ca1854.severity = suggestion +dotnet_diagnostic.ca2000.severity = suggestion +# dotnet_diagnostic.CA2000.severity = warning +dotnet_diagnostic.ca2002.severity = none +dotnet_diagnostic.ca2008.severity = none +dotnet_diagnostic.ca2009.severity = warning +dotnet_diagnostic.ca2011.severity = warning +dotnet_diagnostic.ca2012.severity = warning +dotnet_diagnostic.ca2013.severity = warning +dotnet_diagnostic.ca2014.severity = warning +dotnet_diagnostic.ca2015.severity = warning +dotnet_diagnostic.ca2016.severity = suggestion +dotnet_diagnostic.ca2017.severity = warning +dotnet_diagnostic.ca2018.severity = warning +dotnet_diagnostic.ca2100.severity = warning +dotnet_diagnostic.ca2101.severity = none +dotnet_diagnostic.ca2201.severity = suggestion +# dotnet_diagnostic.CA2201.severity = warning +dotnet_diagnostic.ca2207.severity = warning +dotnet_diagnostic.ca2208.severity = warning +dotnet_diagnostic.ca2211.severity = suggestion +dotnet_diagnostic.ca2213.severity = warning +dotnet_diagnostic.ca2214.severity = suggestion +dotnet_diagnostic.ca2215.severity = warning +dotnet_diagnostic.ca2216.severity = none +dotnet_diagnostic.ca2217.severity = none +dotnet_diagnostic.ca2218.severity = warning +dotnet_diagnostic.ca2219.severity = warning +dotnet_diagnostic.ca2224.severity = warning +dotnet_diagnostic.ca2225.severity = none +dotnet_diagnostic.ca2226.severity = suggestion +dotnet_diagnostic.ca2227.severity = warning +dotnet_diagnostic.ca2229.severity = none +dotnet_diagnostic.ca2231.severity = suggestion +dotnet_diagnostic.ca2234.severity = silent +dotnet_diagnostic.ca2235.severity = none +dotnet_diagnostic.ca2237.severity = none +dotnet_diagnostic.ca2241.severity = warning +dotnet_diagnostic.ca2242.severity = warning +dotnet_diagnostic.ca2243.severity = warning +dotnet_diagnostic.ca2244.severity = warning +dotnet_diagnostic.ca2245.severity = warning +dotnet_diagnostic.ca2246.severity = warning +dotnet_diagnostic.ca2247.severity = warning +dotnet_diagnostic.ca2248.severity = warning +dotnet_diagnostic.ca2249.severity = warning +dotnet_diagnostic.ca2250.severity = warning +dotnet_diagnostic.ca2251.severity = warning +dotnet_diagnostic.ca2252.severity = none +dotnet_diagnostic.ca2253.severity = warning +dotnet_diagnostic.ca2254.severity = none +dotnet_diagnostic.ca2255.severity = none +dotnet_diagnostic.ca2256.severity = none +dotnet_diagnostic.ca2257.severity = none +dotnet_diagnostic.ca2258.severity = none + +# IDE1006 +dotnet_diagnostic.ide1006.severity = warning + +# camel_case_style - Define the camelCase style +dotnet_naming_style.camel_case_style.capitalization = camel_case +# pascal_case_style - Define the PascalCase style +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# first_upper_style - The first character must start with an upper-case character +dotnet_naming_style.first_upper_style.capitalization = first_word_upper +# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I' +dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case +dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I +# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T' +dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case +dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T +# disallowed_style - Anything that has this style applied is marked as disallowed +dotnet_naming_style.disallowed_style.capitalization = pascal_case +dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ +dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ +dotnet_naming_style.internal_error_style.capitalization = pascal_case +dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____ +dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____ + +dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal +dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const +dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field +dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group +dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style +dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning + +dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal +dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly +dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field +dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group +dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style +dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning + +dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal +dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field +dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group +dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style +dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error + +# Other + +dotnet_style_operator_placement_when_wrapping = beginning_of_line + + +# Not verified + +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +# IDE0230 +csharp_style_prefer_utf8_string_literals = true:suggestion + +# ReSharper +resharper_csharp_empty_block_style = together_same_line + +csharp_wrap_arguments_style = chop_if_long +csharp_wrap_chained_method_calls = chop_if_long + +# ReSharper properties +resharper_csharp_wrap_after_declaration_lpar = true +resharper_csharp_wrap_parameters_style = chop_if_long \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 2e503d0..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Swagger to HTML - -on: - push: - branches: - - swaggerhub - -jobs: - generate-and-commit-html: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '14' - - - name: Install Redoc CLI - run: npm install -g redoc-cli - - - name: Generate HTML from Swagger YAML - run: redoc-cli bundle swagger.yaml -o node-output/swagger.html - - - name: Commit and Push HTML - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add node-output/swagger.html - git commit -m "Generate HTML from Swagger YAML" || echo "No changes to commit" - git push origin HEAD:swaggerhub diff --git a/Directory.Packages.props b/Directory.Packages.props index a9605f2..aa16be3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,15 +4,24 @@ false - - - + + + + + + + + + + - + + + \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/DoctorsHelp.Application.Contracts.csproj b/src/Application/DoctorsHelp.Application.Contracts/DoctorsHelp.Application.Contracts.csproj index a613ac5..0efbdd7 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/DoctorsHelp.Application.Contracts.csproj +++ b/src/Application/DoctorsHelp.Application.Contracts/DoctorsHelp.Application.Contracts.csproj @@ -1,10 +1,8 @@ + - - - \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/IAppointmentService.cs b/src/Application/DoctorsHelp.Application.Contracts/IAppointmentService.cs index 6aacce2..2e2c83f 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/IAppointmentService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/IAppointmentService.cs @@ -4,11 +4,11 @@ namespace DoctorsHelp.Application.Contracts; public interface IAppointmentService { - Appointment Create(User patient, Schedule schedule); + Appointment Create(Guid patientId, Guid scheduleId); - Appointment GetAppointment(int patientId); + Appointment? GetAppointment(Guid patientId); - Appointment Update(int id, Dictionary data); + Appointment? Update(Guid id, Dictionary data); - bool Delete(int id); -} \ No newline at end of file + bool Delete(Guid id); +} diff --git a/src/Application/DoctorsHelp.Application.Contracts/IEmployeeService.cs b/src/Application/DoctorsHelp.Application.Contracts/IEmployeeService.cs index 1ea302c..f05b4c5 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/IEmployeeService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/IEmployeeService.cs @@ -4,13 +4,11 @@ namespace DoctorsHelp.Application.Contracts; public interface IEmployeeService { - Employee Create(User user, Specialization specialization, string graduate, string experience); + Employee Create(Guid userId, Guid specializationId, string graduate, string experience); - Employee GetEmployee(); + Employee? GetEmployee(Guid employeeId); - Employee GetById(int id); + Employee? Update(Guid id, Dictionary data); - Employee Update(int id, Dictionary data); - - bool Delete(int id); + bool Delete(Guid id); } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/IReviewService.cs b/src/Application/DoctorsHelp.Application.Contracts/IReviewService.cs index a36b487..9c298b9 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/IReviewService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/IReviewService.cs @@ -4,11 +4,11 @@ namespace DoctorsHelp.Application.Contracts; public interface IReviewService { - Review Create(Appointment appointment, int grade, string comment); + Review Create(Guid appointmentId, int? grade, string comment); - Review GetReview(int appointmentId); + Review? GetReview(Guid reviewId); - Review Update(int id, Dictionary data); + Review? Update(Guid id, Dictionary data); - bool Delete(int id); + bool Delete(Guid id); } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/IScheduleService.cs b/src/Application/DoctorsHelp.Application.Contracts/IScheduleService.cs index 9bc72e0..37253dc 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/IScheduleService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/IScheduleService.cs @@ -4,11 +4,11 @@ namespace DoctorsHelp.Application.Contracts; public interface IScheduleService { - Review Create(Employee employee, DateTime dateStart, DateTime dateEnd); + Schedule Create(Guid employeeId, DateTime? dateStart, DateTime? dateEnd); - Review GeSchedule(int employeeId); + Schedule? GetSchedule(Guid scheduleId); - Review Update(int id, Dictionary data); + Schedule? Update(Guid id, Dictionary data); - bool Delete(int id); + bool Delete(Guid id); } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/ISpecializationService.cs b/src/Application/DoctorsHelp.Application.Contracts/ISpecializationService.cs index 9591000..04fc389 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/ISpecializationService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/ISpecializationService.cs @@ -6,9 +6,9 @@ public interface ISpecializationService { Specialization Create(string name, string description); - Specialization GetSpecialization(int id); + Specialization? GetSpecialization(Guid id); - Specialization Update(int id, Dictionary data); + Specialization? Update(Guid id, Dictionary data); - bool Delete(int id); + bool Delete(Guid id); } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/IUserService.cs b/src/Application/DoctorsHelp.Application.Contracts/IUserService.cs index 999f393..8123b02 100644 --- a/src/Application/DoctorsHelp.Application.Contracts/IUserService.cs +++ b/src/Application/DoctorsHelp.Application.Contracts/IUserService.cs @@ -4,13 +4,11 @@ namespace DoctorsHelp.Application.Contracts; public interface IUserService { - User Register(string name, string surname, string phone, string email, string password, DateTime birthdate); + User Register(string name, string surname, string phone, string email, string password, DateOnly? birthdate); - User Login(string phone, string password); + User? GetUser(Guid id); - User GetUser(int id); + User? UpdateUser(Guid id, Dictionary data); - User Update(int id, Dictionary data); - - bool Delete(int id); + bool DeleteUser(Guid id); } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/AppointmentService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/AppointmentService.cs new file mode 100644 index 0000000..8c65a42 --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/AppointmentService.cs @@ -0,0 +1,97 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class AppointmentService : IAppointmentService +{ + private readonly IAppointmentRepository _appointmentRepository; + private readonly IUserRepository _patientRepository; + private readonly IScheduleRepository _scheduleRepository; + + public AppointmentService(IAppointmentRepository appointmentRepository, IUserRepository userRepository, IScheduleRepository scheduleRepository) + { + _appointmentRepository = appointmentRepository; + _patientRepository = userRepository; + _scheduleRepository = scheduleRepository; + } + + public Appointment Create(Guid patientId, Guid scheduleId) + { + User? patient = UserConverter.UserModelToUser(_patientRepository.GetUser(patientId)); + Schedule? schedule = ScheduleConverter.ScheduleModelToSchedule(_scheduleRepository.GetSchedule(scheduleId)); + + if (patient is null) + throw new Exception("Patient doesnt exist"); + if (schedule is null) + throw new Exception("Schedule doesnt exist"); + + var appointment = new Appointment + { + Id = Guid.NewGuid(), + Patient = patient, + Schedule = schedule, + }; + _appointmentRepository.AddAppointment(appointment); + return appointment; + } + + public Appointment? GetAppointment(Guid patientId) + { + var appointmentModel = _appointmentRepository.GetAppointment(patientId); + + if (appointmentModel is not null) + { + appointmentModel.Patient = _patientRepository.GetUser(appointmentModel.PatientId); + appointmentModel.Schedule = _scheduleRepository.GetSchedule(appointmentModel.ScheduleId); + } + + return AppointmentConverter.AppointmentModelToAppointment(appointmentModel); + } + + public Appointment? Update(Guid id, Dictionary data) + { + AppointmentModel? appointmentToUpdate = _appointmentRepository.GetAppointment(id); + + if (appointmentToUpdate is null) + throw new Exception("No such appointment"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "patientId": + Guid patientId; + if (Guid.TryParse(entry.Value, out patientId)) + appointmentToUpdate.PatientId = patientId; + break; + case "scheduleId": + Guid scheduleId; + if (Guid.TryParse(entry.Value, out scheduleId)) + appointmentToUpdate.ScheduleId = scheduleId; + break; + case "status": + int status; + if (int.TryParse(entry.Value, out status)) + appointmentToUpdate.Status = status; + break; + } + } + + var appointment = AppointmentConverter.AppointmentModelToAppointment(appointmentToUpdate); + + if (appointment is null) + return null; + + _appointmentRepository.UpdateAppointment(appointment); + + return AppointmentConverter.AppointmentModelToAppointment(appointmentToUpdate); + } + + public bool Delete(Guid id) + { + return _appointmentRepository.Delete(new Appointment { Id = id, }); + } +} diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/EmployeeService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/EmployeeService.cs new file mode 100644 index 0000000..7028669 --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/EmployeeService.cs @@ -0,0 +1,100 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class EmployeeService : IEmployeeService +{ + private readonly IEmployeeRepository _employeeRepository; + private readonly IUserRepository _userRepository; + private readonly ISpecializationRepository _specializationRepository; + + public EmployeeService(IEmployeeRepository appointmentRepository, IUserRepository userRepository, ISpecializationRepository specializationRepository) + { + _employeeRepository = appointmentRepository; + _userRepository = userRepository; + _specializationRepository = specializationRepository; + } + + public Employee Create(Guid userId, Guid specializationId, string graduate, string experience) + { + User? user = UserConverter.UserModelToUser(_userRepository.GetUser(userId)); + Specialization? specialization = SpecializationConverter.SpecializationModelToSpecialization(_specializationRepository.GetSpecialization(specializationId)); + + if (user is null) + throw new Exception("user doesnt exist"); + if (specialization is null) + throw new Exception("specialization doesnt exist"); + + var employee = new Employee + { + Id = Guid.NewGuid(), + User = user, + Specialization = specialization, + Graduate = graduate, + Experience = experience, + }; + _employeeRepository.AddEmployee(employee); + return employee; + } + + public Employee? GetEmployee(Guid employeeId) + { + EmployeeModel? employeeModel = _employeeRepository.GetEmployee(employeeId); + + if (employeeModel is not null) + { + employeeModel.User = _userRepository.GetUser(employeeModel.UserId); + employeeModel.Specialization = _specializationRepository.GetSpecialization(employeeModel.SpecializationId); + } + + return EmployeeConverter.EmployeeModelToEmployee(employeeModel); + } + + public Employee? Update(Guid id, Dictionary data) + { + EmployeeModel? employeeToUpdate = _employeeRepository.GetEmployee(id); + + if (employeeToUpdate is null) + throw new Exception("No such employee"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "UserId": + Guid userId; + if (Guid.TryParse(entry.Value, out userId)) + employeeToUpdate.UserId = userId; + break; + case "SpecializationId": + Guid specializationId; + if (Guid.TryParse(entry.Value, out specializationId)) + employeeToUpdate.SpecializationId = specializationId; + break; + case "Graduate": + employeeToUpdate.Graduate = entry.Value; + break; + case "Experience": + employeeToUpdate.Experience = entry.Value; + break; + } + } + + var employee = EmployeeConverter.EmployeeModelToEmployee(employeeToUpdate); + + if (employee is null) + return null; + + _employeeRepository.UpdateEmployee(employee); + + return EmployeeConverter.EmployeeModelToEmployee(employeeToUpdate); + } + + public bool Delete(Guid id) + { + return _employeeRepository.Delete(new Employee { Id = id, }); + } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/ReviewService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/ReviewService.cs new file mode 100644 index 0000000..2f8cf4b --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/ReviewService.cs @@ -0,0 +1,85 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class ReviewService : IReviewService +{ + private readonly IReviewRepository _reviewRepository; + private readonly IAppointmentRepository _appointmentRepository; + + public ReviewService(IReviewRepository reviewRepository, IAppointmentRepository appointmentRepository) + { + _reviewRepository = reviewRepository; + _appointmentRepository = appointmentRepository; + } + + public Review Create(Guid appointmentId, int? grade, string comment) + { + Appointment? appointment = AppointmentConverter.AppointmentModelToAppointment(_appointmentRepository.GetAppointment(appointmentId)); + + if (appointment is null) + throw new Exception("appointment doesnt exist"); + + var review = new Review + { + Id = Guid.NewGuid(), + Appointment = appointment, + Grade = grade, + Comment = comment, + }; + _reviewRepository.AddReview(review); + return review; + } + + public Review? GetReview(Guid reviewId) + { + var reviewModel = _reviewRepository.GetReview(reviewId); + + if (reviewModel is not null) + reviewModel.Appointment = _appointmentRepository.GetAppointment(reviewModel.AppointmentId); + + return ReviewConverter.ReviewModelToReview(reviewModel); + } + + public Review? Update(Guid id, Dictionary data) + { + ReviewModel? reviewToUpdate = _reviewRepository.GetReview(id); + + if (reviewToUpdate is null) + throw new Exception("No such review"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "appointmentId": + Guid appointmentId; + if (Guid.TryParse(entry.Value, out appointmentId)) + reviewToUpdate.AppointmentId = appointmentId; + break; + case "rating": + int grade; + if (int.TryParse(entry.Value, out grade)) + reviewToUpdate.Grade = grade; + break; + case "comment": + reviewToUpdate.Comment = entry.Value; + break; + } + } + + var review = ReviewConverter.ReviewModelToReview(reviewToUpdate); + + _reviewRepository.UpdateReview(review); + + return ReviewConverter.ReviewModelToReview(reviewToUpdate); + } + + public bool Delete(Guid id) + { + return _reviewRepository.Delete(new Review { Id = id }); + } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/ScheduleService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/ScheduleService.cs new file mode 100644 index 0000000..7a7e262 --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/ScheduleService.cs @@ -0,0 +1,86 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class ScheduleService : IScheduleService +{ + private readonly IScheduleRepository _scheduleRepository; + private readonly IEmployeeRepository _employeeRepository; + + public ScheduleService(IScheduleRepository scheduleRepository, IEmployeeRepository employeeRepository) + { + _scheduleRepository = scheduleRepository; + _employeeRepository = employeeRepository; + } + + public Schedule Create(Guid employeeId, DateTime? dateStart, DateTime? dateEnd) + { + Employee? employee = EmployeeConverter.EmployeeModelToEmployee(_employeeRepository.GetEmployee(employeeId)); + + if (employee is null) + throw new Exception("employee doesnt exist"); + + var schedule = new Schedule + { + Id = Guid.NewGuid(), + Employee = employee, + DateStart = dateStart, + DateEnd = dateEnd, + }; + _scheduleRepository.AddSchedule(schedule); + return schedule; + } + + public Schedule? GetSchedule(Guid scheduleId) + { + var scheduleModel = _scheduleRepository.GetSchedule(scheduleId); + + if (scheduleModel is not null) + scheduleModel.Employee = _employeeRepository.GetEmployee(scheduleModel.EmployeeId); + + return ScheduleConverter.ScheduleModelToSchedule(scheduleModel); + } + + public Schedule? Update(Guid id, Dictionary data) + { + ScheduleModel? scheduleToUpdate = _scheduleRepository.GetSchedule(id); + + if (scheduleToUpdate is null) + throw new Exception("No such schedule"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "employeeId": + Guid employeeId; + if (Guid.TryParse(entry.Value, out employeeId)) + scheduleToUpdate.EmployeeId = employeeId; + break; + case "dateStart": + scheduleToUpdate.DateStart = new DateTime(Convert.ToInt32(entry.Value)); + break; + case "dateEnd": + scheduleToUpdate.DateEnd = new DateTime(Convert.ToInt32(entry.Value)); + break; + } + } + + var schedule = ScheduleConverter.ScheduleModelToSchedule(scheduleToUpdate); + + if (schedule is null) + return null; + + _scheduleRepository.UpdateSchedule(schedule); + + return ScheduleConverter.ScheduleModelToSchedule(scheduleToUpdate); + } + + public bool Delete(Guid id) + { + return _scheduleRepository.Delete(new Schedule { Id = id, }); + } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/SpecializationService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/SpecializationService.cs new file mode 100644 index 0000000..97d6eb8 --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/SpecializationService.cs @@ -0,0 +1,70 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class SpecializationService : ISpecializationService +{ + private readonly ISpecializationRepository _specializationRepository; + + public SpecializationService(ISpecializationRepository specializationRepository) + { + _specializationRepository = specializationRepository; + } + + public Specialization Create(string name, string description) + { + var specialization = new Specialization + { + Id = Guid.NewGuid(), + Name = name, + Description = description, + }; + _specializationRepository.AddSpecialization(specialization); + return specialization; + } + + public Specialization? GetSpecialization(Guid id) + { + SpecializationModel? specializationModel = _specializationRepository.GetSpecialization(id); + + return SpecializationConverter.SpecializationModelToSpecialization(specializationModel); + } + + public Specialization? Update(Guid id, Dictionary data) + { + SpecializationModel? specializationToUpdate = _specializationRepository.GetSpecialization(id); + + if (specializationToUpdate is null) + throw new Exception("No such specialization"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "name": + specializationToUpdate.Name = entry.Value; + break; + case "description": + specializationToUpdate.Description = entry.Value; + break; + } + } + + var specialization = SpecializationConverter.SpecializationModelToSpecialization(specializationToUpdate); + + if (specialization is null) + return null; + + _specializationRepository.UpdateSpecialization(specialization); + + return SpecializationConverter.SpecializationModelToSpecialization(specializationToUpdate); + } + + public bool Delete(Guid id) + { + return _specializationRepository.Delete(new Specialization { Id = id }); + } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Contracts/Services/UserService.cs b/src/Application/DoctorsHelp.Application.Contracts/Services/UserService.cs new file mode 100644 index 0000000..885680f --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Contracts/Services/UserService.cs @@ -0,0 +1,80 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Converters; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Application.Contracts.Services; + +public class UserService : IUserService +{ + private readonly IUserRepository _userRepository; + + public UserService(IUserRepository userRepository) + { + _userRepository = userRepository; + } + + public User Register(string name, string surname, string phone, string email, string password, DateOnly? birthdate) + { + var user = new User + { + Id = Guid.NewGuid(), + Name = name, + Surname = surname, + HashedPassword = password, + Phone = phone, + Email = email, + Birthdate = birthdate, + }; + _userRepository.Add(user); + return user; + } + + public User? GetUser(Guid id) + { + var userModel = _userRepository.GetUser(id); + + return UserConverter.UserModelToUser(userModel); + } + + public User? UpdateUser(Guid id, Dictionary data) + { + UserModel? userToUpdate = _userRepository.GetUser(id); + + if (userToUpdate is null) + throw new Exception("No such user"); + + foreach (var entry in data) + { + switch (entry.Key) + { + case "name": + userToUpdate.Name = entry.Value; + break; + case "surname": + userToUpdate.Surname = entry.Value; + break; + case "phone": + userToUpdate.Phone = entry.Value; + break; + case "email": + userToUpdate.Email = entry.Value; + break; + } + } + + var user = UserConverter.UserModelToUser(userToUpdate); + + if (user is null) + return null; + + _userRepository.UpdateUser(user); + + return UserConverter.UserModelToUser(userToUpdate); + } + + public bool DeleteUser(Guid id) + { + return _userRepository.Delete(new User { Id = id }); + } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Models/Appointment.cs b/src/Application/DoctorsHelp.Application.Models/Appointment.cs index 3f2a153..b43508d 100644 --- a/src/Application/DoctorsHelp.Application.Models/Appointment.cs +++ b/src/Application/DoctorsHelp.Application.Models/Appointment.cs @@ -1,16 +1,16 @@ namespace DoctorsHelp.Application.Models; -public class Appointment +public class Appointment : IEntity { - public int Id { get; set; } + public Guid? Id { get; set; } public User? Patient { get; set; } public Schedule? Schedule { get; set; } - public DateTime CreatedAt { get; set; } + public DateTime? CreatedAt { get; set; } - public DateTime UpdatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } - public int Status { get; set; } + public int? Status { get; set; } } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Models/DoctorsHelp.Application.Models.csproj b/src/Application/DoctorsHelp.Application.Models/DoctorsHelp.Application.Models.csproj index 35e3d84..6b512ec 100644 --- a/src/Application/DoctorsHelp.Application.Models/DoctorsHelp.Application.Models.csproj +++ b/src/Application/DoctorsHelp.Application.Models/DoctorsHelp.Application.Models.csproj @@ -1,2 +1 @@ - - + diff --git a/src/Application/DoctorsHelp.Application.Models/Employee.cs b/src/Application/DoctorsHelp.Application.Models/Employee.cs index 66440a8..7a14f36 100644 --- a/src/Application/DoctorsHelp.Application.Models/Employee.cs +++ b/src/Application/DoctorsHelp.Application.Models/Employee.cs @@ -1,12 +1,12 @@ namespace DoctorsHelp.Application.Models; -public class Employee +public class Employee : IEntity { - public int Id { get; set; } + public Guid? Id { get; set; } public User? User { get; set; } - public int Specialization { get; set; } + public Specialization? Specialization { get; set; } public string? Graduate { get; set; } diff --git a/src/Application/DoctorsHelp.Application.Models/Intefaces/IEntity.cs b/src/Application/DoctorsHelp.Application.Models/Intefaces/IEntity.cs new file mode 100644 index 0000000..ec68373 --- /dev/null +++ b/src/Application/DoctorsHelp.Application.Models/Intefaces/IEntity.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Application.Models; + +public interface IEntity +{ + public Guid? Id { get; } +} \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Models/Review.cs b/src/Application/DoctorsHelp.Application.Models/Review.cs index a3e6769..7b6e005 100644 --- a/src/Application/DoctorsHelp.Application.Models/Review.cs +++ b/src/Application/DoctorsHelp.Application.Models/Review.cs @@ -1,16 +1,16 @@ namespace DoctorsHelp.Application.Models; -public class Review +public class Review : IEntity { - public int Id { get; set; } + public Guid? Id { get; set; } public Appointment? Appointment { get; set; } - public int Grade { get; set; } + public int? Grade { get; set; } public string? Comment { get; set; } - public DateTime CreatedAt { get; set; } + public DateTime? CreatedAt { get; set; } - public DateTime UpdatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Models/Schedule.cs b/src/Application/DoctorsHelp.Application.Models/Schedule.cs index 2d04da3..00bd13c 100644 --- a/src/Application/DoctorsHelp.Application.Models/Schedule.cs +++ b/src/Application/DoctorsHelp.Application.Models/Schedule.cs @@ -1,14 +1,14 @@ namespace DoctorsHelp.Application.Models; -public class Schedule +public class Schedule : IEntity { - public int Id { get; set; } + public Guid? Id { get; set; } public Employee? Employee { get; set; } - public DateTime DateStart { get; set; } + public DateTime? DateStart { get; set; } - public DateTime DateEnd { get; set; } + public DateTime? DateEnd { get; set; } - public int Status { get; set; } + public int? Status { get; set; } } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application.Models/Specialization.cs b/src/Application/DoctorsHelp.Application.Models/Specialization.cs index 335b580..e61d7ba 100644 --- a/src/Application/DoctorsHelp.Application.Models/Specialization.cs +++ b/src/Application/DoctorsHelp.Application.Models/Specialization.cs @@ -1,8 +1,8 @@ namespace DoctorsHelp.Application.Models; -public class Specialization +public class Specialization : IEntity { - public int Id { get; set; } + public Guid? Id { get; set; } public string? Name { get; set; } diff --git a/src/Application/DoctorsHelp.Application.Models/User.cs b/src/Application/DoctorsHelp.Application.Models/User.cs index 2e5a3b2..b93a5ed 100644 --- a/src/Application/DoctorsHelp.Application.Models/User.cs +++ b/src/Application/DoctorsHelp.Application.Models/User.cs @@ -1,8 +1,8 @@ namespace DoctorsHelp.Application.Models; -public class User +public class User : IEntity { - public Guid Id { get; set; } + public Guid? Id { get; set; } public string? Name { get; set; } @@ -14,7 +14,7 @@ public class User public string? HashedPassword { get; set; } - public DateOnly Birthdate { get; set; } + public DateOnly? Birthdate { get; set; } public string? Role { get; set; } } \ No newline at end of file diff --git a/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs b/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs index f0449dc..7cefcf8 100644 --- a/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs +++ b/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs @@ -1,3 +1,5 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Contracts.Services; using Microsoft.Extensions.DependencyInjection; namespace DoctorsHelp.Application.Extensions; @@ -6,7 +8,12 @@ public static class ServiceCollectionExtensions { public static IServiceCollection AddApplication(this IServiceCollection collection) { - // TODO: add services + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); return collection; } } \ No newline at end of file diff --git a/src/DoctorsHelp/DoctorsHelp.csproj b/src/DoctorsHelp/DoctorsHelp.csproj index f201af4..7d12243 100644 --- a/src/DoctorsHelp/DoctorsHelp.csproj +++ b/src/DoctorsHelp/DoctorsHelp.csproj @@ -1,15 +1,17 @@ - - + + - + + + diff --git a/src/DoctorsHelp/Program.cs b/src/DoctorsHelp/Program.cs index 7fe3860..9af0284 100644 --- a/src/DoctorsHelp/Program.cs +++ b/src/DoctorsHelp/Program.cs @@ -16,23 +16,23 @@ builder.Services.AddSingleton(sp => sp.GetRequiredService>().Value); builder.Services.AddApplication(); -builder.Services.AddInfrastructurePersistence(); + +builder.Services.AddInfrastructurePersistence(builder.Configuration); builder.Services .AddControllers() .AddNewtonsoftJson() .AddPresentationHttp(); -builder.Services.AddSwaggerGen().AddEndpointsApiExplorer(); - +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); builder.Host.AddPlatformSerilog(builder.Configuration); builder.Services.AddUtcDateTimeProvider(); WebApplication app = builder.Build(); -app.UseRouting(); app.UseSwagger(); app.UseSwaggerUI(); - +app.UseRouting(); app.MapControllers(); await app.RunAsync(); \ No newline at end of file diff --git a/src/DoctorsHelp/Util/Profiles.cs b/src/DoctorsHelp/Util/Profiles.cs new file mode 100644 index 0000000..79dfd46 --- /dev/null +++ b/src/DoctorsHelp/Util/Profiles.cs @@ -0,0 +1,8 @@ +namespace DoctorsHelp.Util; + +public enum Profiles +{ + Local, + + Prod, +} \ No newline at end of file diff --git a/src/DoctorsHelp/appsettings.Local.json b/src/DoctorsHelp/appsettings.Local.json index a26180e..9d3ce72 100644 --- a/src/DoctorsHelp/appsettings.Local.json +++ b/src/DoctorsHelp/appsettings.Local.json @@ -2,13 +2,7 @@ "Infrastructure": { "Persistence": { "Postgres": { - "Host": "localhost", - "Port": 6432, - "Database": "postgres", - "Username": "postgres", - "Password": "postgres", - "SslMode": "Prefer", - "Pooling": true + "ConnectionString": "Host=rc1b-i7lu7rt5vmg38nh0.mdb.yandexcloud.net;Port=6432;Database=oop;Username=g1phy;Password=fPr-KsP-h9W-q48;" } } }, @@ -17,6 +11,18 @@ "Host": "localhost:9092" } }, + "Kestrel": { + "Endpoints": { + "gRPC": { + "Url": "http://*:3071", + "Protocols": "Http2" + }, + "http": { + "Url": "http://*:3070", + "Protocols": "Http1" + } + } + }, "Platform": { "Environment": "Local" }, diff --git a/src/DoctorsHelp/appsettings.json b/src/DoctorsHelp/appsettings.json index 46b1ad6..181682c 100644 --- a/src/DoctorsHelp/appsettings.json +++ b/src/DoctorsHelp/appsettings.json @@ -3,20 +3,14 @@ "Infrastructure": { "Persistence": { "Postgres": { - "Host": "", - "Port": -1, - "Database": "", - "Username": "", - "Password": "", - "SslMode": "Prefer", - "Pooling": true + "ConnectionString": "Host=rc1b-i7lu7rt5vmg38nh0.mdb.yandexcloud.net;Port=6432;Database=oop;Username=g1phy;Password=fPr-KsP-h9W-q48;" } - }, + } }, "Presentation": { }, "Platform": { - "Environment": "", + "Environment": "" }, "Sentry": { "Enabled": true, @@ -30,8 +24,12 @@ "Kestrel": { "Endpoints": { "gRPC": { - "Url": "http://*:8070", + "Url": "http://*:3071", "Protocols": "Http2" + }, + "http": { + "Url": "http://*:3070", + "Protocols": "Http1" } } }, diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs new file mode 100644 index 0000000..1a7e9a8 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs @@ -0,0 +1,30 @@ +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Contexts; + +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext() { } + + public ApplicationDbContext(DbContextOptions options) : base(options) { } + + required public DbSet Users { get; set; } + + required public DbSet Appointments { get; set; } + + required public DbSet Employees { get; set; } + + required public DbSet Reviews { get; set; } + + required public DbSet Schedules { get; set; } + + required public DbSet Specializations { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly); + + // base.OnModelCreating(modelBuilder); + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/AppointmentConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/AppointmentConverter.cs new file mode 100644 index 0000000..07970ac --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/AppointmentConverter.cs @@ -0,0 +1,23 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class AppointmentConverter +{ + public static Appointment? AppointmentModelToAppointment(AppointmentModel? appointmentModel) + { + if (appointmentModel is null) + return null; + + return new Appointment + { + Id = appointmentModel.Id, + Patient = UserConverter.UserModelToUser(appointmentModel.Patient), + Schedule = ScheduleConverter.ScheduleModelToSchedule(appointmentModel.Schedule), + CreatedAt = appointmentModel.CreatedAt, + UpdatedAt = appointmentModel.UpdatedAt, + Status = appointmentModel.Status, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/EmployeeConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/EmployeeConverter.cs new file mode 100644 index 0000000..a5340c1 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/EmployeeConverter.cs @@ -0,0 +1,22 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class EmployeeConverter +{ + public static Employee? EmployeeModelToEmployee(EmployeeModel? employeeModel) + { + if (employeeModel is null) + return null; + + return new Employee + { + Id = employeeModel.Id, + User = UserConverter.UserModelToUser(employeeModel.User), + Specialization = SpecializationConverter.SpecializationModelToSpecialization(employeeModel.Specialization), + Graduate = employeeModel.Graduate, + Experience = employeeModel.Experience, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ReviewConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ReviewConverter.cs new file mode 100644 index 0000000..d8eb167 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ReviewConverter.cs @@ -0,0 +1,20 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class ReviewConverter +{ + public static Review ReviewModelToReview(ReviewModel? reviewModel) + { + return new Review + { + Id = reviewModel?.Id, + Appointment = AppointmentConverter.AppointmentModelToAppointment(reviewModel?.Appointment), + Grade = reviewModel?.Grade, + Comment = reviewModel?.Comment, + CreatedAt = reviewModel?.CreatedAt, + UpdatedAt = reviewModel?.UpdatedAt, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ScheduleConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ScheduleConverter.cs new file mode 100644 index 0000000..791f904 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/ScheduleConverter.cs @@ -0,0 +1,19 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class ScheduleConverter +{ + public static Schedule? ScheduleModelToSchedule(ScheduleModel? scheduleModel) + { + return new Schedule + { + Id = scheduleModel?.Id, + Employee = EmployeeConverter.EmployeeModelToEmployee(scheduleModel?.Employee), + DateStart = scheduleModel?.DateStart, + DateEnd = scheduleModel?.DateEnd, + Status = scheduleModel?.Status, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/SpecializationConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/SpecializationConverter.cs new file mode 100644 index 0000000..13602d2 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/SpecializationConverter.cs @@ -0,0 +1,20 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class SpecializationConverter +{ + public static Specialization? SpecializationModelToSpecialization(SpecializationModel? specializationModel) + { + if (specializationModel is null) + return null; + + return new Specialization + { + Id = specializationModel.Id, + Name = specializationModel.Name, + Description = specializationModel.Description, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/UserConverter.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/UserConverter.cs new file mode 100644 index 0000000..9b13393 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Converters/UserConverter.cs @@ -0,0 +1,25 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Converters; + +public class UserConverter +{ + public static User? UserModelToUser(UserModel? userModel) + { + if (userModel is null) + return null; + + return new User + { + Id = userModel.Id, + Name = userModel.Name, + Surname = userModel.Surname, + Phone = userModel.Phone, + Email = userModel.Email, + HashedPassword = userModel.HashedPassword, + Birthdate = userModel.Birthdate, + Role = userModel.Role, + }; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj index 2aec2b3..e3a3b03 100644 --- a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj @@ -9,4 +9,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs index dbad899..af5a45b 100644 --- a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs @@ -1,25 +1,25 @@ -using DoctorsHelp.Application.Abstractions.Persistence; -using DoctorsHelp.Infrastructure.Persistence.Migrations; -using DoctorsHelp.Infrastructure.Persistence.Plugins; -using Itmo.Dev.Platform.Postgres.Extensions; -using Itmo.Dev.Platform.Postgres.Plugins; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using DoctorsHelp.Infrastructure.Persistence.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace DoctorsHelp.Infrastructure.Persistence.Extensions; public static class ServiceCollectionExtensions { - public static IServiceCollection AddInfrastructurePersistence(this IServiceCollection collection) + public static IServiceCollection AddInfrastructurePersistence(this IServiceCollection collection, IConfiguration configuration) { - collection.AddPlatformPostgres(builder => builder.BindConfiguration("Infrastructure:Persistence:Postgres")); - collection.AddSingleton(); - - collection.AddPlatformMigrations(typeof(IAssemblyMarker).Assembly); - collection.AddHostedService(); - - // TODO: add repositories - collection.AddScoped(); + collection.AddDbContext(options => + options.UseNpgsql(configuration.GetSection("Infrastructure:Persistence:Postgres:ConnectionString").Value)); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); + collection.AddScoped(); return collection; } } \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IAppointmentRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IAppointmentRepository.cs new file mode 100644 index 0000000..8982c42 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IAppointmentRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface IAppointmentRepository +{ + void AddAppointment(Appointment appointment); + + AppointmentModel? GetAppointment(Guid id); + + void UpdateAppointment(Appointment appointment); + + bool Delete(Appointment appointment); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IEmployeeRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IEmployeeRepository.cs new file mode 100644 index 0000000..59ff70f --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IEmployeeRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface IEmployeeRepository +{ + void AddEmployee(Employee employee); + + EmployeeModel? GetEmployee(Guid id); + + void UpdateEmployee(Employee employee); + + bool Delete(Employee employee); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IReviewRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IReviewRepository.cs new file mode 100644 index 0000000..1310db0 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IReviewRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface IReviewRepository +{ + void AddReview(Review review); + + ReviewModel? GetReview(Guid id); + + void UpdateReview(Review review); + + bool Delete(Review review); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IScheduleRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IScheduleRepository.cs new file mode 100644 index 0000000..f8f51a5 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IScheduleRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface IScheduleRepository +{ + void AddSchedule(Schedule schedule); + + ScheduleModel? GetSchedule(Guid id); + + void UpdateSchedule(Schedule schedule); + + bool Delete(Schedule schedule); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/ISpecializationRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/ISpecializationRepository.cs new file mode 100644 index 0000000..e8ee539 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/ISpecializationRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface ISpecializationRepository +{ + void AddSpecialization(Specialization specialization); + + SpecializationModel? GetSpecialization(Guid id); + + void UpdateSpecialization(Specialization specialization); + + bool Delete(Specialization specialization); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IUserRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IUserRepository.cs new file mode 100644 index 0000000..106c1c4 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Interfaces/IUserRepository.cs @@ -0,0 +1,15 @@ +using DoctorsHelp.Application.Models; +using Infrastructure.Persistence.Models; + +namespace DoctorsHelp.Infrastructure.Persistence.Interfaces; + +public interface IUserRepository +{ + void Add(User user); + + UserModel? GetUser(Guid id); + + void UpdateUser(User user); + + bool Delete(User user); +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.Designer.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.Designer.cs new file mode 100644 index 0000000..d6d67d1 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.Designer.cs @@ -0,0 +1,247 @@ +// +using System; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace DoctorsHelp.Infrastructure.Persistence.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240411191337_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Infrastructure.Persistence.Models.AppointmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PatientId") + .HasColumnType("uuid"); + + b.Property("ScheduleId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PatientId"); + + b.HasIndex("ScheduleId"); + + b.ToTable("Appointments"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.EmployeeModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Experience") + .HasColumnType("text"); + + b.Property("Graduate") + .HasColumnType("text"); + + b.Property("SpecializationId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SpecializationId"); + + b.HasIndex("UserId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ReviewModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppointmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Grade") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AppointmentId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ScheduleModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.ToTable("Schedules"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.SpecializationModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Specializations"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.UserModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Birthdate") + .HasColumnType("date"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("HashedPassword") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("text"); + + b.Property("Surname") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.AppointmentModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.UserModel", "Patient") + .WithMany() + .HasForeignKey("PatientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Infrastructure.Persistence.Models.ScheduleModel", "Schedule") + .WithMany() + .HasForeignKey("ScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Patient"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.EmployeeModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.SpecializationModel", "Specialization") + .WithMany() + .HasForeignKey("SpecializationId"); + + b.HasOne("Infrastructure.Persistence.Models.UserModel", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Specialization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ReviewModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.AppointmentModel", "Appointment") + .WithMany() + .HasForeignKey("AppointmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Appointment"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ScheduleModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.EmployeeModel", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.cs new file mode 100644 index 0000000..82fbad7 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/20240411191337_Initial.cs @@ -0,0 +1,193 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DoctorsHelp.Infrastructure.Persistence.Migrations; + +/// +public partial class Initial : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Specializations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + Description = table.Column(type: "text", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Specializations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + Surname = table.Column(type: "text", nullable: true), + Phone = table.Column(type: "text", nullable: true), + Email = table.Column(type: "text", nullable: true), + HashedPassword = table.Column(type: "text", nullable: true), + Birthdate = table.Column(type: "date", nullable: true), + Role = table.Column(type: "text", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Employees", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + SpecializationId = table.Column(type: "uuid", nullable: true), + Graduate = table.Column(type: "text", nullable: true), + Experience = table.Column(type: "text", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Employees", x => x.Id); + table.ForeignKey( + name: "FK_Employees_Specializations_SpecializationId", + column: x => x.SpecializationId, + principalTable: "Specializations", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Employees_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Schedules", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + EmployeeId = table.Column(type: "uuid", nullable: false), + DateStart = table.Column(type: "timestamp with time zone", nullable: true), + DateEnd = table.Column(type: "timestamp with time zone", nullable: true), + Status = table.Column(type: "integer", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Schedules", x => x.Id); + table.ForeignKey( + name: "FK_Schedules_Employees_EmployeeId", + column: x => x.EmployeeId, + principalTable: "Employees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Appointments", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + PatientId = table.Column(type: "uuid", nullable: false), + ScheduleId = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: true), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true), + Status = table.Column(type: "integer", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Appointments", x => x.Id); + table.ForeignKey( + name: "FK_Appointments_Schedules_ScheduleId", + column: x => x.ScheduleId, + principalTable: "Schedules", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Appointments_Users_PatientId", + column: x => x.PatientId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Reviews", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AppointmentId = table.Column(type: "uuid", nullable: false), + Grade = table.Column(type: "integer", nullable: true), + Comment = table.Column(type: "text", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: true), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_Reviews", x => x.Id); + table.ForeignKey( + name: "FK_Reviews_Appointments_AppointmentId", + column: x => x.AppointmentId, + principalTable: "Appointments", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Appointments_PatientId", + table: "Appointments", + column: "PatientId"); + + migrationBuilder.CreateIndex( + name: "IX_Appointments_ScheduleId", + table: "Appointments", + column: "ScheduleId"); + + migrationBuilder.CreateIndex( + name: "IX_Employees_SpecializationId", + table: "Employees", + column: "SpecializationId"); + + migrationBuilder.CreateIndex( + name: "IX_Employees_UserId", + table: "Employees", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Reviews_AppointmentId", + table: "Reviews", + column: "AppointmentId"); + + migrationBuilder.CreateIndex( + name: "IX_Schedules_EmployeeId", + table: "Schedules", + column: "EmployeeId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Reviews"); + + migrationBuilder.DropTable( + name: "Appointments"); + + migrationBuilder.DropTable( + name: "Schedules"); + + migrationBuilder.DropTable( + name: "Employees"); + + migrationBuilder.DropTable( + name: "Specializations"); + + migrationBuilder.DropTable( + name: "Users"); + } +} diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..4427002 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,244 @@ +// +using System; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace DoctorsHelp.Infrastructure.Persistence.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Infrastructure.Persistence.Models.AppointmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PatientId") + .HasColumnType("uuid"); + + b.Property("ScheduleId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PatientId"); + + b.HasIndex("ScheduleId"); + + b.ToTable("Appointments"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.EmployeeModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Experience") + .HasColumnType("text"); + + b.Property("Graduate") + .HasColumnType("text"); + + b.Property("SpecializationId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SpecializationId"); + + b.HasIndex("UserId"); + + b.ToTable("Employees"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ReviewModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppointmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Grade") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AppointmentId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ScheduleModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.ToTable("Schedules"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.SpecializationModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Specializations"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.UserModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Birthdate") + .HasColumnType("date"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("HashedPassword") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("text"); + + b.Property("Surname") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.AppointmentModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.UserModel", "Patient") + .WithMany() + .HasForeignKey("PatientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Infrastructure.Persistence.Models.ScheduleModel", "Schedule") + .WithMany() + .HasForeignKey("ScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Patient"); + + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.EmployeeModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.SpecializationModel", "Specialization") + .WithMany() + .HasForeignKey("SpecializationId"); + + b.HasOne("Infrastructure.Persistence.Models.UserModel", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Specialization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ReviewModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.AppointmentModel", "Appointment") + .WithMany() + .HasForeignKey("AppointmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Appointment"); + }); + + modelBuilder.Entity("Infrastructure.Persistence.Models.ScheduleModel", b => + { + b.HasOne("Infrastructure.Persistence.Models.EmployeeModel", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/AppointmentModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/AppointmentModel.cs new file mode 100644 index 0000000..faf9d11 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/AppointmentModel.cs @@ -0,0 +1,22 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class AppointmentModel : IEntity +{ + public Guid? Id { get; set; } + + public Guid PatientId { get; set; } + + public Guid ScheduleId { get; set; } + + public DateTime? CreatedAt { get; set; } + + public DateTime? UpdatedAt { get; set; } + + public int? Status { get; set; } + + public UserModel? Patient { get; set; } + + public ScheduleModel? Schedule { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/EmployeeModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/EmployeeModel.cs new file mode 100644 index 0000000..593b8a2 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/EmployeeModel.cs @@ -0,0 +1,20 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class EmployeeModel : IEntity +{ + public Guid? Id { get; set; } + + public Guid UserId { get; set; } + + public Guid SpecializationId { get; set; } + + public string? Graduate { get; set; } + + public string? Experience { get; set; } + + public UserModel? User { get; set; } + + public SpecializationModel? Specialization { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ReviewModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ReviewModel.cs new file mode 100644 index 0000000..aee4dcb --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ReviewModel.cs @@ -0,0 +1,20 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class ReviewModel : IEntity +{ + public Guid? Id { get; set; } + + public Guid AppointmentId { get; set; } + + public int? Grade { get; set; } + + public string? Comment { get; set; } + + public DateTime? CreatedAt { get; set; } + + public DateTime? UpdatedAt { get; set; } + + public AppointmentModel? Appointment { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ScheduleModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ScheduleModel.cs new file mode 100644 index 0000000..3408b18 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/ScheduleModel.cs @@ -0,0 +1,18 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class ScheduleModel : IEntity +{ + public Guid? Id { get; set; } + + public Guid EmployeeId { get; set; } + + public DateTime? DateStart { get; set; } + + public DateTime? DateEnd { get; set; } + + public int? Status { get; set; } + + public EmployeeModel? Employee { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/SpecializationModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/SpecializationModel.cs new file mode 100644 index 0000000..c488c97 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/SpecializationModel.cs @@ -0,0 +1,12 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class SpecializationModel : IEntity +{ + public Guid? Id { get; set; } + + public string? Name { get; set; } + + public string? Description { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/UserModel.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/UserModel.cs new file mode 100644 index 0000000..785feda --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Models/UserModel.cs @@ -0,0 +1,22 @@ +using DoctorsHelp.Application.Models; + +namespace Infrastructure.Persistence.Models; + +public class UserModel : IEntity +{ + public Guid? Id { get; set; } + + public string? Name { get; set; } + + public string? Surname { get; set; } + + public string? Phone { get; set; } + + public string? Email { get; set; } + + public string? HashedPassword { get; set; } + + public DateOnly? Birthdate { get; set; } + + public string? Role { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/AppointmentRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/AppointmentRepository.cs new file mode 100644 index 0000000..19ce9e3 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/AppointmentRepository.cs @@ -0,0 +1,64 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class AppointmentRepository : RepositoryBase, IAppointmentRepository +{ + public AppointmentRepository(ApplicationDbContext context) : base(context) + { + } + + public AppointmentModel? GetAppointment(Guid id) + { + return GetEntry(new Appointment { Id = id })?.Entity; + } + + public void UpdateAppointment(Appointment appointment) + { + Update(appointment); + } + + public bool Delete(Appointment appointment) + { + Remove(appointment); + return true; + } + + public void AddAppointment(Appointment appointment) + { + Add(appointment); + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Appointments; + + protected override AppointmentModel MapFrom(Appointment entity) + { + return new AppointmentModel + { + Id = entity.Id, + PatientId = entity.Patient?.Id ?? Guid.Empty, + ScheduleId = entity.Schedule?.Id ?? Guid.Empty, + CreatedAt = entity.CreatedAt, + UpdatedAt = entity.UpdatedAt, + Status = entity.Status, + }; + } + + protected override bool Equal(Appointment entity, AppointmentModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(AppointmentModel model, Appointment entity) + { + model.PatientId = entity.Patient?.Id ?? Guid.Empty; + model.ScheduleId = entity.Schedule?.Id ?? Guid.Empty; + model.CreatedAt = entity.CreatedAt; + model.UpdatedAt = entity.UpdatedAt; + model.Status = entity.Status; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/EmployeeRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/EmployeeRepository.cs new file mode 100644 index 0000000..8825f14 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/EmployeeRepository.cs @@ -0,0 +1,62 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class EmployeeRepository : RepositoryBase, IEmployeeRepository +{ + public EmployeeRepository(ApplicationDbContext context) : base(context) + { + } + + public EmployeeModel? GetEmployee(Guid id) + { + return GetEntry(new Employee { Id = id })?.Entity; + } + + public void UpdateEmployee(Employee employee) + { + Update(employee); + } + + public bool Delete(Employee employee) + { + Remove(employee); + return true; + } + + public void AddEmployee(Employee employee) + { + Add(employee); + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Employees; + + protected override EmployeeModel MapFrom(Employee entity) + { + return new EmployeeModel + { + Id = entity.Id, + UserId = entity.User?.Id ?? Guid.Empty, + SpecializationId = entity.Specialization?.Id ?? Guid.Empty, + Graduate = entity.Graduate, + Experience = entity.Experience, + }; + } + + protected override bool Equal(Employee entity, EmployeeModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(EmployeeModel model, Employee entity) + { + model.UserId = entity.User?.Id ?? Guid.Empty; + model.SpecializationId = entity.Specialization?.Id ?? Guid.Empty; + model.Graduate = entity.Graduate; + model.Experience = entity.Experience; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/RepositoryBase.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/RepositoryBase.cs new file mode 100644 index 0000000..331b9d2 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/RepositoryBase.cs @@ -0,0 +1,72 @@ +using DoctorsHelp.Application.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public abstract class RepositoryBase + where TEntity : IEntity + where TModel : class, IEntity +{ + #pragma warning disable IDE0032 + private readonly DbContext _context; + + protected DbContext Context => _context; + + protected RepositoryBase(DbContext context) + { + this._context = context; + } + + protected abstract DbSet DbSet { get; } + + public void Add(TEntity entity) + { + TModel model = MapFrom(entity); + DbSet.Add(model); + _context.SaveChanges(); + } + + public void AddRange(IEnumerable entities) + { + IEnumerable models = entities.Select(MapFrom); + DbSet.AddRange(models); + } + + public void Update(TEntity entity) + { + EntityEntry? entry = GetEntry(entity); + + if (entry is null) + return; + + UpdateModel(entry.Entity, entity); + entry.State = EntityState.Modified; + _context.SaveChanges(); + } + + public void Remove(TEntity entity) + { + EntityEntry? entry = GetEntry(entity); + + if (entry is null) + return; + + entry.State = entry.State is EntityState.Added ? EntityState.Detached : EntityState.Deleted; + } + + protected abstract TModel MapFrom(TEntity entity); + + protected abstract bool Equal(TEntity entity, TModel model); + + protected abstract void UpdateModel(TModel model, TEntity entity); + + protected EntityEntry? GetEntry(TEntity entity) + { + TModel? existing = DbSet.FirstOrDefault(model => model.Id == entity.Id); + + return existing is not null + ? _context.Entry(existing) + : null; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ReviewRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ReviewRepository.cs new file mode 100644 index 0000000..bd27fa1 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ReviewRepository.cs @@ -0,0 +1,64 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class ReviewRepository : RepositoryBase, IReviewRepository +{ + public ReviewRepository(ApplicationDbContext context) : base(context) + { + } + + public ReviewModel? GetReview(Guid id) + { + return GetEntry(new Review { Id = id })?.Entity; + } + + public void UpdateReview(Review review) + { + Update(review); + } + + public bool Delete(Review review) + { + Remove(review); + return true; + } + + public void AddReview(Review review) + { + Add(review); + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Reviews; + + protected override ReviewModel MapFrom(Review entity) + { + return new ReviewModel + { + Id = entity.Id, + AppointmentId = entity.Appointment?.Id ?? Guid.Empty, + Grade = entity.Grade, + Comment = entity.Comment, + CreatedAt = entity.CreatedAt, + UpdatedAt = entity.UpdatedAt, + }; + } + + protected override bool Equal(Review entity, ReviewModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(ReviewModel model, Review entity) + { + model.AppointmentId = entity.Appointment?.Id ?? Guid.Empty; + model.Grade = entity.Grade; + model.Comment = entity.Comment; + model.CreatedAt = entity.CreatedAt; + model.UpdatedAt = entity.UpdatedAt; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ScheduleRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ScheduleRepository.cs new file mode 100644 index 0000000..38d6a74 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/ScheduleRepository.cs @@ -0,0 +1,62 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class ScheduleRepository : RepositoryBase, IScheduleRepository +{ + public ScheduleRepository(ApplicationDbContext context) : base(context) + { + } + + public ScheduleModel? GetSchedule(Guid id) + { + return GetEntry(new Schedule { Id = id })?.Entity; + } + + public void UpdateSchedule(Schedule schedule) + { + Update(schedule); + } + + public bool Delete(Schedule schedule) + { + Remove(schedule); + return true; + } + + public void AddSchedule(Schedule schedule) + { + Add(schedule); + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Schedules; + + protected override ScheduleModel MapFrom(Schedule entity) + { + return new ScheduleModel + { + Id = entity.Id, + EmployeeId = entity.Employee?.Id ?? Guid.Empty, + DateStart = entity.DateStart, + DateEnd = entity.DateEnd, + Status = entity.Status, + }; + } + + protected override bool Equal(Schedule entity, ScheduleModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(ScheduleModel model, Schedule entity) + { + model.EmployeeId = entity.Employee?.Id ?? Guid.Empty; + model.DateStart = entity.DateStart; + model.DateEnd = entity.DateEnd; + model.Status = entity.Status; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/SpecializationRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/SpecializationRepository.cs new file mode 100644 index 0000000..3388392 --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/SpecializationRepository.cs @@ -0,0 +1,59 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class SpecializationRepository : RepositoryBase, ISpecializationRepository +{ + public SpecializationRepository(ApplicationDbContext context) : base(context) + { + } + + public void UpdateSpecialization(Specialization specialization) + { + Update(specialization); + } + + public SpecializationModel? GetSpecialization(Guid id) + { + SpecializationModel? entry = GetEntry(new Specialization { Id = id })?.Entity; + return entry; + } + + public bool Delete(Specialization specialization) + { + Remove(specialization); + return true; + } + + public void AddSpecialization(Specialization specialization) + { + Add(specialization); + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Specializations; + + protected override SpecializationModel MapFrom(Specialization entity) + { + return new SpecializationModel + { + Id = entity.Id, + Name = entity.Name, + Description = entity.Description, + }; + } + + protected override bool Equal(Specialization entity, SpecializationModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(SpecializationModel model, Specialization entity) + { + model.Name = entity.Name; + model.Description = entity.Description; + } +} \ No newline at end of file diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/UserRepository.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/UserRepository.cs new file mode 100644 index 0000000..0bfc42b --- /dev/null +++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Repositories/UserRepository.cs @@ -0,0 +1,63 @@ +using DoctorsHelp.Application.Models; +using DoctorsHelp.Infrastructure.Persistence.Contexts; +using DoctorsHelp.Infrastructure.Persistence.Interfaces; +using Infrastructure.Persistence.Models; +using Microsoft.EntityFrameworkCore; + +namespace DoctorsHelp.Infrastructure.Persistence.Repositories; + +public class UserRepository : RepositoryBase, IUserRepository +{ + public UserRepository(ApplicationDbContext context) : base(context) + { + } + + public UserModel? GetUser(Guid id) + { + return GetEntry(new User { Id = id })?.Entity; + } + + public void UpdateUser(User user) + { + Update(user); + } + + public bool Delete(User user) + { + Remove(user); + return true; + } + + protected override DbSet DbSet => ((ApplicationDbContext)Context).Users; + + protected override UserModel MapFrom(User entity) + { + return new UserModel + { + Id = entity.Id, + Name = entity.Name, + Surname = entity.Surname, + Phone = entity.Phone, + Email = entity.Email, + HashedPassword = entity.HashedPassword, + Birthdate = entity.Birthdate, + Role = entity.Role, + }; + } + + protected override bool Equal(User entity, UserModel model) + { + return entity.Id == model.Id; + } + + protected override void UpdateModel(UserModel model, User entity) + { + model.Name = entity.Name; + model.Surname = entity.Surname; + model.Phone = entity.Phone; + model.Email = entity.Email; + model.HashedPassword = entity.HashedPassword; + model.Birthdate = entity.Birthdate; + model.Role = entity.Role; + } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/AppointmentController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/AppointmentController.cs new file mode 100644 index 0000000..12aa80c --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/AppointmentController.cs @@ -0,0 +1,72 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using DoctorsHelp.Presentation.Http.Responses; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; +[ApiController] +[Route("appointment")] +public class AppointmentController : ControllerBase +{ + private readonly IAppointmentService _appointmentService; + + public AppointmentController(IAppointmentService appointmentService) + { + _appointmentService = appointmentService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var appointment = _appointmentService.GetAppointment(id); + if (appointment == null) + { + return NotFound(); + } + + return Ok(appointment); + } + + [HttpPost] + public ActionResult Post([FromBody] AppointmentPost data) + { + try + { + var createdAppointment = _appointmentService.Create(data.PatientId, data.ScheduleId); + return CreatedAtAction(nameof(Get), new { id = createdAppointment.Id }, createdAppointment); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while creating the appointment." + ex); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedAppointment = _appointmentService.Update(id, data); + return Ok(updatedAppointment); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _appointmentService.Delete(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/EmployeeController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/EmployeeController.cs new file mode 100644 index 0000000..abe3959 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/EmployeeController.cs @@ -0,0 +1,77 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; + +[ApiController] +[Route("employee")] +public class EmployeeController : ControllerBase +{ + private readonly IEmployeeService _employeeService; + + public EmployeeController(IEmployeeService employeeService) + { + _employeeService = employeeService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var employee = _employeeService.GetEmployee(id); + if (employee == null) + { + return NotFound(); + } + + return Ok(employee); + } + + [HttpPost] + public ActionResult Post([FromBody] EmployeePost data) + { + if (string.IsNullOrWhiteSpace(data.Graduate) || string.IsNullOrWhiteSpace(data.Experience)) + { + return BadRequest("User, Specialization, Graduate, and Experience are required."); + } + + try + { + var createdEmployee = _employeeService.Create(data.UserId, data.SpecializationId, data.Graduate, data.Experience); + return CreatedAtAction(nameof(Get), new { id = createdEmployee.Id }, createdEmployee); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while creating the employee. " + ex.Message); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedEmployee = _employeeService.Update(id, data); + return Ok(updatedEmployee); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _employeeService.Delete(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ReviewController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ReviewController.cs new file mode 100644 index 0000000..d981ac3 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ReviewController.cs @@ -0,0 +1,77 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; + +[ApiController] +[Route("review")] +public class ReviewController : ControllerBase +{ + private readonly IReviewService _reviewService; + + public ReviewController(IReviewService reviewService) + { + _reviewService = reviewService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var review = _reviewService.GetReview(id); + if (review == null) + { + return NotFound(); + } + + return Ok(review); + } + + [HttpPost] + public ActionResult Post([FromBody] ReviewPost data) + { + if (data.Grade < 1 || string.IsNullOrWhiteSpace(data.Comment)) + { + return BadRequest("Appointment, Grade, and Comment are required."); + } + + try + { + var createdReview = _reviewService.Create(data.AppointmentId, data.Grade, data.Comment); + return CreatedAtAction(nameof(Get), new { id = createdReview.Id }, createdReview); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while creating the review. " + ex.Message); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedReview = _reviewService.Update(id, data); + return Ok(updatedReview); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _reviewService.Delete(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ScheduleController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ScheduleController.cs new file mode 100644 index 0000000..4c06b88 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/ScheduleController.cs @@ -0,0 +1,82 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; + +[ApiController] +[Route("schedule")] +public class ScheduleController : ControllerBase +{ + private readonly IScheduleService _scheduleService; + + public ScheduleController(IScheduleService scheduleService) + { + _scheduleService = scheduleService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var schedule = _scheduleService.GetSchedule(id); + if (schedule == null) + { + return NotFound(); + } + + return Ok(schedule); + } + + [HttpPost] + public ActionResult Post([FromBody] SchedulePost data) + { + if (data.DateStart == default || data.DateEnd == default) + { + return BadRequest("Employee, DateStart, and DateEnd are required."); + } + + if (data.DateStart >= data.DateEnd) + { + return BadRequest("DateStart must be before DateEnd."); + } + + try + { + var createdSchedule = _scheduleService.Create(data.EmployeeId, data.DateStart, data.DateEnd); + return CreatedAtAction(nameof(Get), new { id = createdSchedule.Id }, createdSchedule); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while creating the schedule. " + ex.Message); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedSchedule = _scheduleService.Update(id, data); + return Ok(updatedSchedule); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _scheduleService.Delete(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/SpecializationController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/SpecializationController.cs new file mode 100644 index 0000000..66bef0e --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/SpecializationController.cs @@ -0,0 +1,75 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; + +[ApiController] +[Route("specialization")] +public class SpecializationController : ControllerBase +{ + private readonly ISpecializationService _specializationService; + + public SpecializationController(ISpecializationService specializationService) + { + _specializationService = specializationService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var specialization = _specializationService.GetSpecialization(id); + if (specialization == null) + return BadRequest("No specialization found with the given id."); + + return Ok(specialization); + } + + [HttpPost] + public ActionResult Post([FromBody] SpecializationPost data) + { + if (data.Name == null || data.Description == null) + { + return BadRequest("Name and Description are required."); + } + + try + { + var createdSpecialization = _specializationService.Create(data.Name, data.Description); + return CreatedAtAction(nameof(Get), new { id = createdSpecialization.Id }, createdSpecialization); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while creating the specialization." + ex); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedSpecialization = _specializationService.Update(id, data); + return Ok(updatedSpecialization); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _specializationService.Delete(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/UserController.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/UserController.cs new file mode 100644 index 0000000..97c6482 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Controllers/UserController.cs @@ -0,0 +1,79 @@ +using DoctorsHelp.Application.Contracts; +using DoctorsHelp.Application.Models; +using DoctorsHelp.Presentation.Http.Requests; +using Microsoft.AspNetCore.Mvc; + +namespace DoctorsHelp.Presentation.Http.Controllers; + +[ApiController] +[Route("user")] +public class UserController : ControllerBase +{ + private readonly IUserService _userService; + + public UserController(IUserService userService) + { + _userService = userService; + } + + [HttpGet("{id}")] + public ActionResult Get(Guid id) + { + var user = _userService.GetUser(id); + if (user == null) + return NotFound(); + + return Ok(user); + } + + [HttpPost] + public ActionResult Post([FromBody] UserPost data) + { + if (string.IsNullOrWhiteSpace(data.Name) || + string.IsNullOrWhiteSpace(data.Surname) || + string.IsNullOrWhiteSpace(data.Phone) || + string.IsNullOrWhiteSpace(data.Email) || + string.IsNullOrWhiteSpace(data.Password)) + { + return BadRequest("All fields are required."); + } + + try + { + var user = _userService.Register(data.Name, data.Surname, data.Phone, data.Email, data.Password, data.Birthdate); + return CreatedAtAction(nameof(Get), new { id = user.Id }, user); + } + catch (Exception ex) + { + return StatusCode(500, "An error occurred while registering the user. " + ex.Message); + } + } + + [HttpPut("{id}")] + public ActionResult Update(Guid id, [FromBody] Dictionary data) + { + try + { + var updatedUser = _userService.UpdateUser(id, data); + return Ok(updatedUser); + } + catch (KeyNotFoundException) + { + return NotFound(); + } + } + + [HttpDelete("{id}")] + public IActionResult Delete(Guid id) + { + var result = _userService.DeleteUser(id); + if (result) + { + return NoContent(); + } + else + { + return NotFound(); + } + } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/DoctorsHelp.Presentation.Http.csproj b/src/Presentation/DoctorsHelp.Presentation.Http/DoctorsHelp.Presentation.Http.csproj index 21d1366..b0f89eb 100644 --- a/src/Presentation/DoctorsHelp.Presentation.Http/DoctorsHelp.Presentation.Http.csproj +++ b/src/Presentation/DoctorsHelp.Presentation.Http/DoctorsHelp.Presentation.Http.csproj @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/AppointmentPost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/AppointmentPost.cs new file mode 100644 index 0000000..62e5d57 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/AppointmentPost.cs @@ -0,0 +1,8 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class AppointmentPost +{ + public Guid PatientId { get; set; } + + public Guid ScheduleId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/EmployeePost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/EmployeePost.cs new file mode 100644 index 0000000..f1d305d --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/EmployeePost.cs @@ -0,0 +1,12 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class EmployeePost +{ + public Guid UserId { get; set; } + + public Guid SpecializationId { get; set; } + + public string? Graduate { get; set; } + + public string? Experience { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/ReviewPost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/ReviewPost.cs new file mode 100644 index 0000000..6dee4f2 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/ReviewPost.cs @@ -0,0 +1,10 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class ReviewPost +{ + public Guid AppointmentId { get; set; } + + public int Grade { get; set; } + + public string? Comment { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SchedulePost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SchedulePost.cs new file mode 100644 index 0000000..cd69cb5 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SchedulePost.cs @@ -0,0 +1,10 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class SchedulePost +{ + public Guid EmployeeId { get; set; } + + public DateTime? DateStart { get; set; } + + public DateTime? DateEnd { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SpecializationPost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SpecializationPost.cs new file mode 100644 index 0000000..92f5848 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/SpecializationPost.cs @@ -0,0 +1,8 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class SpecializationPost +{ + public string? Name { get; set; } + + public string? Description { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Requests/UserPost.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/UserPost.cs new file mode 100644 index 0000000..8eeb26b --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Requests/UserPost.cs @@ -0,0 +1,16 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class UserPost +{ + public string? Name { get; set; } + + public string? Surname { get; set; } + + public string? Phone { get; set; } + + public string? Email { get; set; } + + public string? Password { get; set; } + + public DateOnly Birthdate { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/AppointmentPostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/AppointmentPostResponse.cs new file mode 100644 index 0000000..1e64a72 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/AppointmentPostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Responses; + +public class AppointmentPostResponse +{ + public Guid AppointmentId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/EmployeePostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/EmployeePostResponse.cs new file mode 100644 index 0000000..1b22282 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/EmployeePostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class EmployeePostResponse +{ + public Guid EmployeeId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/ReviewPostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/ReviewPostResponse.cs new file mode 100644 index 0000000..a40f161 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/ReviewPostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class ReviewPostResponse +{ + public Guid ReviewId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SchedulePostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SchedulePostResponse.cs new file mode 100644 index 0000000..6f7fd50 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SchedulePostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class SchedulePostResponse +{ + public Guid ReviewId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SpecializationPostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SpecializationPostResponse.cs new file mode 100644 index 0000000..ad70f09 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/SpecializationPostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class SpecializationPostResponse +{ + public Guid SpecializationId { get; set; } +} \ No newline at end of file diff --git a/src/Presentation/DoctorsHelp.Presentation.Http/Responses/UserPostResponse.cs b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/UserPostResponse.cs new file mode 100644 index 0000000..63f8e60 --- /dev/null +++ b/src/Presentation/DoctorsHelp.Presentation.Http/Responses/UserPostResponse.cs @@ -0,0 +1,6 @@ +namespace DoctorsHelp.Presentation.Http.Requests; + +public class UserPostResponse +{ + public Guid UserId { get; set; } +} \ No newline at end of file