diff --git a/Pipefy.code-workspace b/Pipefy.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/Pipefy.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/Pipefy.csproj b/Pipefy.csproj index 9fe459a..41c67b4 100644 --- a/Pipefy.csproj +++ b/Pipefy.csproj @@ -9,6 +9,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Program.cs b/Program.cs index 60e148d..188fc86 100644 --- a/Program.cs +++ b/Program.cs @@ -22,7 +22,7 @@ class Program var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(provider => { - var config = provider.GetRequiredService().LoadAppSettings(); + var config = provider.GetRequiredService().GetAppSettings(); return new PipefyApiService(config.PIPEFY_API_URL, config.PIPEFY_API_TOKEN); }); serviceCollection.AddSingleton(); @@ -31,7 +31,7 @@ class Program var serviceProvider = serviceCollection.BuildServiceProvider(); var configService = serviceProvider.GetRequiredService(); - var AppSettings = configService.LoadAppSettings(); + var AppSettings = configService.GetAppSettings(); if (AppSettings is null){ Environment.Exit(1); } Console.Clear(); @@ -53,6 +53,7 @@ class Program List databaseData = databaseService.GetDataFromDatabase(AppSettings.DB_PATH); var businessLogic = serviceProvider.GetRequiredService(); List recordsMissingInJson = businessLogic.CompareData(databaseData, jsonList, jsonListGestores); + recordsMissingInJson.AddRange(businessLogic.CompareData(jsonList, databaseData, jsonListGestores)); if (recordsMissingInJson.Count != 0 && recordsMissingInJson != null) { await pipefyApi.CreateRecordsAsync(AppSettings.PIPEFY_TABLE_ID, recordsMissingInJson); @@ -62,7 +63,7 @@ class Program int maxCGestao = recordsMissingInJson.OrderByDescending(s => s.gestores!.Length).First().gestores!.Length; foreach (var record in recordsMissingInJson) { - Console.WriteLine(String.Format($"| ID: {{0,{maxCId}}} | Nome: {{1,{maxCNome}}} | Modalidade: {{2,{maxCMod}}} | Gestão: {{3,{maxCGestao}}} |",record.c_digo_smart,record.nome_da_empresa,record.modalidade,record.gestores)); + Console.WriteLine(String.Format($"| ID: {{0,{maxCId}}} | Nome: {{1,{maxCNome}}} | Modalidade: {{2,{maxCMod}}} | Gestão: {{3,{maxCGestao}}} |", record.c_digo_smart, record.nome_da_empresa, record.modalidade, record.gestores)); } Console.WriteLine(""); } diff --git a/SOLID-Refactoring-Plan.md b/SOLID-Refactoring-Plan.md index f483285..2621918 100644 --- a/SOLID-Refactoring-Plan.md +++ b/SOLID-Refactoring-Plan.md @@ -20,6 +20,7 @@ This document outlines a step-by-step plan to refactor the Pipefy project to com - `Models/`: For data models (move from `data.cs`). - `Mappers/`: For mapping logic between API/DB and domain models (optional, if mapping grows). - [ ] Integrate ORM (e.g., Entity Framework Core) to abstract DB access and ease future DB changes. (Next step) + - Note: Current structure is well-separated; ORM will further improve OCP and testability. - [x] Move or create files as needed for separation of concerns. ## 3. Single Responsibility Principle (SRP) @@ -29,17 +30,21 @@ This document outlines a step-by-step plan to refactor the Pipefy project to com - [x] Extract data mapping logic into `IDataMapper` and `DataMapper`. - [x] Extract business logic (comparison, orchestration) into `IBusinessLogicService` and `BusinessLogicService`. - [x] Remove static business/data methods from `Program.cs` and ensure all logic is in services. + - Note: All main responsibilities are separated. Consider splitting services further if logic grows (e.g., separate API read/write, config providers). ## 4. Open/Closed Principle (OCP) - [x] Define interfaces for each service (already done: IConfigurationService, IPipefyApiService, IDatabaseService, IDataMapper, IBusinessLogicService). - [x] Ensure new data sources or logic can be added by implementing new classes, not modifying existing ones (all main logic is now behind interfaces and DI). + - Note: Future data sources or logic can be added via new classes. ## 5. Liskov Substitution Principle (LSP) - [ ] Ensure all service implementations can be replaced by their interfaces without breaking functionality. + - Note: Add/expand unit tests to verify all service implementations can be swapped without breaking consumers. Ensure interfaces do not expose implementation-specific details. ## 6. Interface Segregation Principle (ISP) - [ ] Keep interfaces focused and small. - [ ] Split large interfaces if needed. + - Note: Review interfaces for granularity. Split any that grow too large or have unrelated methods. ## 7. Dependency Inversion Principle (DIP) - [x] Refactor `Program.cs` to depend on abstractions (interfaces), not concrete classes. @@ -48,10 +53,12 @@ This document outlines a step-by-step plan to refactor the Pipefy project to com ## 8. Testing - [ ] Add or update unit tests for each service. - [ ] Ensure business logic is testable in isolation. + - Note: Prioritize unit tests for business logic and service interfaces. Use mocks/fakes to test substitutability and isolation. ## 9. Documentation - [ ] Update this plan as you progress. - [ ] Document new structure and usage in a `README.md` or similar file. + - Note: Document service responsibilities and interface contracts. Add XML comments to public APIs. --- @@ -61,4 +68,4 @@ This document outlines a step-by-step plan to refactor the Pipefy project to com --- -_Last updated: May 16, 2025_ +_Last updated: May 19, 2025_ diff --git a/Services/ConfigurationService.cs b/Services/ConfigurationService.cs index 120441c..f3abfc2 100644 --- a/Services/ConfigurationService.cs +++ b/Services/ConfigurationService.cs @@ -17,14 +17,5 @@ namespace Pipefy.Services { return _configuration.GetSection("AppSettings").Get()!; } - - public AppSettings LoadAppSettings() - { - var configurationBuilder = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: false); - IConfiguration configuration = configurationBuilder.Build(); - return configuration.GetSection("AppSettings").Get()!; - } } } diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index 3b76108..0fece89 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Data.OleDb; -using System.Text; +using Dapper; using Pipefy.Models; namespace Pipefy.Services @@ -10,38 +10,24 @@ namespace Pipefy.Services public List GetDataFromDatabase(string connSourcePath) { string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + connSourcePath + ";Jet OLEDB:Database Password=gds21;"; - List data = new List(); using (OleDbConnection connection = new OleDbConnection(connectionString)) { connection.Open(); - StringBuilder sqlQuery = new StringBuilder(); - sqlQuery.Append("SELECT cod_smart_cliente, \n"); - sqlQuery.Append(" cliente, \n"); - sqlQuery.Append(" modalidade, \n"); - sqlQuery.Append(" gestao \n"); - sqlQuery.Append("FROM dados_cadastrais \n"); - sqlQuery.Append("WHERE cod_smart_unidade LIKE \"%001\" \n"); - sqlQuery.Append(" AND unidade_gerenciada;"); - using (OleDbCommand command = new OleDbCommand(sqlQuery.ToString(), connection)) + string sqlQuery = @"SELECT cod_smart_cliente AS c_digo_smart, + cliente AS nome_da_empresa, + modalidade, + gestao AS gestores + FROM dados_cadastrais + WHERE cod_smart_unidade LIKE '%001' + AND unidade_gerenciada;"; + var data = connection.Query(sqlQuery).AsList(); + // rec_id is not in the DB, set to empty string + foreach (var item in data) { - using (OleDbDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - ClasseEmpresas record = new ClasseEmpresas - { - c_digo_smart = reader["Cod_Smart_cliente"].ToString(), - nome_da_empresa = reader["Cliente"].ToString(), - modalidade = reader["Modalidade"].ToString(), - gestores = reader["Gestao"].ToString(), - rec_id = "" - }; - data.Add(record); - } - } + item.rec_id = string.Empty; } + return data; } - return data; } } } diff --git a/Services/IConfigurationService.cs b/Services/IConfigurationService.cs index 1a832b2..a4af5d9 100644 --- a/Services/IConfigurationService.cs +++ b/Services/IConfigurationService.cs @@ -5,6 +5,5 @@ namespace Pipefy.Services public interface IConfigurationService { AppSettings GetAppSettings(); - AppSettings LoadAppSettings(); } }