diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..150cf12 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,61 @@ +# This workflow will build and publish a WinUI 3 unpackaged desktop application +# built on .NET. + +name: WinUI 3 unpackaged app + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + + build: + + strategy: + matrix: + configuration: [Release] + platform: [x64, x86] + + runs-on: windows-latest # For a list of available runner types, refer to + # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on + + env: + Solution_Name: '.\REZ\REZ.sln' + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + # Install the .NET Core workload + - name: Install .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 7.0.x + + # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild + - name: Setup MSBuild.exe + uses: microsoft/setup-msbuild@v1.0.2 + + # Restore the application to populate the obj folder with RuntimeIdentifiers + - name: Restore the application + run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration + env: + Configuration: ${{ matrix.configuration }} + + # Create the app by building and publishing the project + - name: Create the app + run: msbuild $env:Solution_Name /t:Publish /p:Configuration=$env:Configuration /p:Platform=$env:Platform + env: + Configuration: ${{ matrix.configuration }} + Platform: ${{ matrix.platform }} + + # Upload the app + - name: Upload app + uses: actions/upload-artifact@v2 + with: + name: Upload app + path: ${{ env.Solution_Name }}\\bin diff --git a/REZ/AccountInfo.xaml b/REZ/AccountInfo.xaml index 6e642f1..abe1fba 100644 --- a/REZ/AccountInfo.xaml +++ b/REZ/AccountInfo.xaml @@ -88,7 +88,7 @@ - + diff --git a/REZ/AccountInfo.xaml.cs b/REZ/AccountInfo.xaml.cs index 3e9f483..4a22d93 100644 --- a/REZ/AccountInfo.xaml.cs +++ b/REZ/AccountInfo.xaml.cs @@ -36,14 +36,14 @@ public AccountInfo() this.InitializeComponent(); UpdateUser(User); Debug.WriteLine($"[AccountInfo] Current User: {User.Name}"); - UpdatePrice(ProductsList); - myListView.ItemsSource = User.ItemsList; + } //---------------------------------------------------------------------------- public void UpdatePrice(List productsList) { + double subtotal = SubtotalValueCalculator(productsList); string subtotalValue = subtotal.ToString("0.00"); double taxa = subtotal * 0.1; @@ -62,9 +62,10 @@ public double SubtotalValueCalculator(List productsList) foreach (Product product in productsList) { - finalValue += product.Price; + Debug.WriteLine($"{product.Name}: {product.Quantity}"); + finalValue += product.FinalPrice; } - + Debug.WriteLine($"[AccountInfo] Valor subtotal final: R$ {finalValue}"); return finalValue; } diff --git a/REZ/AccountsList.cs b/REZ/AccountsList.cs index 3b9e5be..5138ee9 100644 --- a/REZ/AccountsList.cs +++ b/REZ/AccountsList.cs @@ -27,20 +27,20 @@ public static Account SelectedAccount set { selectedAccount = value; } } - public static ShoppingCart Cart { get { return shoppingCart; } set { shoppingCart = value; } } + //---------------------------------------------------------------------------- public AccountsList() { - //Accounts = new List { }; - shoppingCart = InicializeNewShoppingCart(); + shoppingCart = new ShoppingCart(); //Criar a conta no DB } + //---------------------------------------------------------------------------- public static List AddNewAccount(Account account) { @@ -49,6 +49,7 @@ public static List AddNewAccount(Account account) return Accounts; } + //---------------------------------------------------------------------------- public static void RemoveAccount(Account account) { //Remover conta do DB @@ -66,6 +67,7 @@ public static void RemoveAccount(Account account) } + //---------------------------------------------------------------------------- public static Account SwitchAccounts(Account newAccount) { if (Accounts.Count > 0) @@ -91,23 +93,7 @@ public static Account SwitchAccounts(Account newAccount) return SelectedAccount; } - - public void CloseAccounts() - { - //deletar todas as contas do DB - Accounts.Clear(); - InicializeNewShoppingCart(); - - } - - private ShoppingCart InicializeNewShoppingCart() - { - Random random = new Random(); // mudar para um gerador de Id de respeito - string newOrderId = random.Next(0, 100).ToString(); - return new ShoppingCart(newOrderId); - - } - + //---------------------------------------------------------------------------- public static List GetAvailableUsers() { List availableUsers = new List(); diff --git a/REZ/AddAccountModal.xaml.cs b/REZ/AddAccountModal.xaml.cs index f22cfec..51cbaa3 100644 --- a/REZ/AddAccountModal.xaml.cs +++ b/REZ/AddAccountModal.xaml.cs @@ -62,21 +62,17 @@ private void InputsValidation() // Maybe later we can add the INotifyPropertyChanged interface. private void InputName_TextChange(object sender, TextChangedEventArgs e) { - Regex regex = new Regex("^[a-zA-ZÀ-ÿ]{1,20}$"); - if (String.IsNullOrEmpty(Name.Text)) + Regex regex = new Regex("^([a-zA-ZÀ-ÿ]{3,10})+([ a-zA-ZÀ-ÿ]{0,20})$"); + if (!regex.IsMatch(Name.Text)) { ErrorMessage_Name.Visibility = Visibility.Visible; - ErrorMessage_Name.Text = Name.Text + "Por favor digite um nome."; IsNameInputValid = false; + ErrorMessage_Name.Text = String.IsNullOrEmpty(Name.Text) + ? $"Por favor digite um nome." + : $"{Name.Text} - não e um nome valido. Por favor insira outro nome."; } - else if (!regex.IsMatch(Name.Text)) + else { - ErrorMessage_Name.Visibility = Visibility.Visible; - ErrorMessage_Name.Text = Name.Text + " não é um nome válido. Por favor insira outro nome."; - IsNameInputValid = false; - } - else - { ErrorMessage_Name.Visibility = Visibility.Collapsed; IsNameInputValid = true; } @@ -89,9 +85,7 @@ private void InputName_TextChange(object sender, TextChangedEventArgs e) // Maybe later we can add the INotifyPropertyChanged interface. private void CPFNumber_TextChange(object sender, TextChangedEventArgs e) { - TextBox textBox = sender as TextBox; - string formattedCPF = FormatCPF(textBox.Text); if (formattedCPF != textBox.Text) @@ -100,8 +94,6 @@ private void CPFNumber_TextChange(object sender, TextChangedEventArgs e) textBox.SelectionStart = formattedCPF.Length; } - - Regex regex = new Regex("^\\d{3}\\.?\\d{3}\\.?\\d{3}-?\\d{2}$"); if (String.IsNullOrEmpty(CPF.Text)) { ErrorMessage_CPF.Visibility = Visibility.Visible; @@ -112,7 +104,7 @@ private void CPFNumber_TextChange(object sender, TextChangedEventArgs e) //{ // ErrorMessage_CPF.Visibility = Visibility.Visible; // ErrorMessage_CPF.Text = CPF.Text + " não é um CPF válido. Por favor insira um número de CPF."; - // IsCPFInputValid = false; + // IsCPFInputValid = false; //} else { @@ -120,9 +112,10 @@ private void CPFNumber_TextChange(object sender, TextChangedEventArgs e) IsCPFInputValid = true; } InputsValidation(); - } + //---------------------------------------------------------------------------- + // This will validate the CPF number with its specific format and logic private bool ValidateCPF(string cpf) { string digitsOnly = new string(cpf.Where(char.IsDigit).ToArray()); @@ -163,9 +156,14 @@ private bool ValidateCPF(string cpf) int.Parse(digitsOnly[10].ToString()) == secondDigit; } + + //---------------------------------------------------------------------------- + // This method will autoformat user input adding dots and dash to the CPF number + // for correct formatting. + // By this, the user will only need to input 1234568900 and the TextBox field + // will live update to 123.456.789-00. private string FormatCPF(string cpf) { - string digitsOnly = new string(cpf.Where(char.IsDigit).ToArray()); if (digitsOnly.Length > 11) @@ -186,10 +184,7 @@ private string FormatCPF(string cpf) { formattedCPF = formattedCPF.Insert(11, "-"); } - return formattedCPF; } - - } } diff --git a/REZ/CloseAccountConfirmation.xaml.cs b/REZ/CloseAccountConfirmation.xaml.cs index 3897bff..8a1e28e 100644 --- a/REZ/CloseAccountConfirmation.xaml.cs +++ b/REZ/CloseAccountConfirmation.xaml.cs @@ -27,5 +27,6 @@ public CloseAccountConfirmation() { this.InitializeComponent(); } + } } diff --git a/REZ/FoodMenu.xaml.cs b/REZ/FoodMenu.xaml.cs index b79cfdb..2947946 100644 --- a/REZ/FoodMenu.xaml.cs +++ b/REZ/FoodMenu.xaml.cs @@ -193,8 +193,8 @@ public void SwitchUser_ButtonClick(object sender, RoutedEventArgs e) } - //---------------------------------------------------------------------------- - private async void CreateAccount(object sender, RoutedEventArgs e) + //---------------------------------------------------------------------------- + private async void CreateAccount(object sender, RoutedEventArgs e) { ContentDialog dialog = new ContentDialog(); dialog.XamlRoot = this.XamlRoot; @@ -226,5 +226,6 @@ public void UpdateUser(Account user) Greetings.Text = $"Olá, {User.Name}!"; ShoppingCart.DefineUser(User); } + } } \ No newline at end of file diff --git a/REZ/Product.cs b/REZ/Product.cs index dd3f804..e311599 100644 --- a/REZ/Product.cs +++ b/REZ/Product.cs @@ -14,6 +14,7 @@ public class Product : ICloneable private string category; private string subCategory; private int quantity; + private double finalPrice = 0; public string OrderId { @@ -44,6 +45,12 @@ public double Price { get { return quantity > 0? price * quantity : price; } set { price = value; } + } + + public double FinalPrice + { + get { return finalPrice; } + set { finalPrice = value; } } public string Description { @@ -79,7 +86,9 @@ public object Clone() return new Product(this.Name, this.Description, this.Price, this.imageSource, this.Category) { SubCategory = this.SubCategory, - Quantity = this.Quantity + Quantity = this.Quantity, + OrderId = this.OrderId, + }; } diff --git a/REZ/REZ.csproj b/REZ/REZ.csproj index d4723c3..eceb04f 100644 --- a/REZ/REZ.csproj +++ b/REZ/REZ.csproj @@ -205,4 +205,7 @@ true + + false + diff --git a/REZ/ShoppingCart.cs b/REZ/ShoppingCart.cs index e8f1ca9..7d15681 100644 --- a/REZ/ShoppingCart.cs +++ b/REZ/ShoppingCart.cs @@ -15,7 +15,7 @@ public class ShoppingCart // public AccountsList OpenAccounts; public static Account User = AccountsList.SelectedAccount; public double TotalPrice; - public string OrderId; + public static string OrderId = "0"; public static List OrderProducts { @@ -24,9 +24,10 @@ public static List OrderProducts } //---------------------------------------------------------------------------- - public ShoppingCart(string orderId) + public ShoppingCart() { - OrderId = orderId; + OrderId = (int.Parse(OrderId) + 1).ToString(); + if (User != null) { @@ -112,15 +113,21 @@ public void CompleteOrder(List accountsToDivide, List orderIte foreach (Product item in orderItemsList) { double valueForEach = item.DivideItemPrice(accountsToDivide, accountsQuantity); + + Debug.WriteLine($"contas para dividir: {accountsToDivide.Count}"); foreach (Account account in accountsToDivide) { + Product newItem = item.Clone() as Product; + //newItem.Price = valueForEach; bool addNewItem = true; + foreach (Product itemInAccount in account.ItemsList) { - if (item.Name == itemInAccount.Name) + if (newItem.Name == itemInAccount.Name) { - itemInAccount.Quantity += item.Quantity; + itemInAccount.Quantity += newItem.Quantity; + itemInAccount.FinalPrice += valueForEach; addNewItem = false; } @@ -128,12 +135,14 @@ public void CompleteOrder(List accountsToDivide, List orderIte if (addNewItem) { - Product newItem = item.Clone() as Product; - newItem.Price = valueForEach; + newItem.FinalPrice += valueForEach; account.AddItem(newItem); } + Debug.WriteLine($"adddNewItem: {addNewItem}"); + Debug.WriteLine($"items na conta: {account.ItemsList.Count}"); } + item.RemoveItemFromCart(); } diff --git a/REZ/ShoppingCartModal.xaml b/REZ/ShoppingCartModal.xaml index d573ae2..9f046bf 100644 --- a/REZ/ShoppingCartModal.xaml +++ b/REZ/ShoppingCartModal.xaml @@ -65,10 +65,10 @@ - + - + diff --git a/REZ/ShoppingCartModal.xaml.cs b/REZ/ShoppingCartModal.xaml.cs index aa55d9c..ead7bbe 100644 --- a/REZ/ShoppingCartModal.xaml.cs +++ b/REZ/ShoppingCartModal.xaml.cs @@ -15,6 +15,7 @@ using Newtonsoft.Json; using static System.Net.WebRequestMethods; using System.Diagnostics; +using System.Security.Principal; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -43,30 +44,35 @@ public ShoppingCartModal(ShoppingCart shoppingCart, ContentDialog dialog) DataContext = this; } - private void CountryComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + //---------------------------------------------------------------------------- + private void AddAccountToSplit(object sender, RoutedEventArgs e) { - List selectedAccounts = new List(); - + CheckBox checkBox = sender as CheckBox; + + foreach (Account account in CreatedAccounts) + { + if (account.Name == (string)checkBox.Content && account.CPF == (string)checkBox.Tag && account.IsEnabled == true) + { + AccountsToDivide = ShoppingCart.AddSplitAccount(account); + break; + } + } } - private void SplitAccount_Updater(object sender, SelectionChangedEventArgs e) + //---------------------------------------------------------------------------- + private void RemoveAccountToSplit(object sender, RoutedEventArgs e) { - Debug.WriteLine($"Created accounts: {CreatedAccounts.Count}"); - foreach (var account in CreatedAccounts) + CheckBox comboBox = sender as CheckBox; + + foreach (Account account in ShoppingCart.AccountsToDivide) { - if (account.IsSelected) - { - ShoppingCart.AddSplitAccount(account); - } - else + if (account.Name == (string)comboBox.Content && account.CPF == (string)comboBox.Tag) { - ShoppingCart.RemoveSplitAccount(account); + AccountsToDivide = ShoppingCart.AddSplitAccount(account); + break; } - } - - } //---------------------------------------------------------------------------- diff --git a/REZ/SwitchAccountModal.xaml b/REZ/SwitchAccountModal.xaml index ba54065..6080804 100644 --- a/REZ/SwitchAccountModal.xaml +++ b/REZ/SwitchAccountModal.xaml @@ -7,7 +7,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" - Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> + Background="White"> diff --git a/REZ/SwitchAccountModal.xaml.cs b/REZ/SwitchAccountModal.xaml.cs index 85f133d..6b5045c 100644 --- a/REZ/SwitchAccountModal.xaml.cs +++ b/REZ/SwitchAccountModal.xaml.cs @@ -38,6 +38,7 @@ public SwitchAccountModal() } + //---------------------------------------------------------------------------- private void SelectedUserChanged(object sender, SelectionChangedEventArgs e) { UserToChange = AccountsOptions.SelectedItem as Account; diff --git a/doc/dev/DevelopmentReport.md b/doc/dev/DevelopmentReport.md new file mode 100644 index 0000000..41d65ec --- /dev/null +++ b/doc/dev/DevelopmentReport.md @@ -0,0 +1,65 @@ +## REZ Development Report (INF-0999) +Provided this is the Final Project of the training course in Microsoft technologies at the Institute of Computing at the State University of Campinas (UNICAMP), it is important that the students follow some base criteria about each subject taught during the course. For that reason, the following topics were considered during development: + +- C# Programming Language and known software architecture patterns; +- Code versioning; +- Hosting; +- Project Management; +- User Experience; +- User Interface Programming; +- Safe Programming; + +### Programming and Architecture Pattern +### Code Versioning +For code versioning we used the Git + GitHub remote repository workflow. Branch names are specific for a feature (or set of features) that the developers are currently working, so Pull Requests can be concise and easy to read. They can also be attached to an specific issue so both are closed after a merge. + +For this project we have been using the [Shared Repository Model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#shared-repository-model), in which all collaborators are granted access to the single shared repository. Each branch is created to meet an specific issue requirements so we can merge the code via a PR with code review. + +Branch names can be specified using a simple pattern like: +``` +add_functional_shoppingcart +fix_menu_images +doc_devreport +``` + +The commit message standards we are using may follow (but not only) these rules: +``` +* feat – a new feature is introduced with the changes +* fix – a bug fix has occurred +* chore – changes that do not relate to a fix or feature and don't modify src or test files (for example updating dependencies) +* refactor – refactored code that neither fixes a bug nor adds a feature +* docs – updates to documentation such as a the README or other markdown files +* style – changes that do not affect the meaning of the code, likely related to code formatting such as white-space, missing semi-colons, and so on. +* test – including new or correcting previous tests +* perf – performance improvements +* ci – continuous integration related +* build – changes that affect the build system or external dependencies +* revert – reverts a previous commit +``` +On the GitHub repository, we have been opening and tracking issues for each feature or bugfix. The issues have a simple template for messages, in which a `Description` and `Further Information` should be provided. Issues can be written in English or Portuguese. + +![Alt text](./assets/issue-example-1.png) + +- [GitHub Repository](https://github.com/lknknm/REZ-menu-app); +- You can see Open and Closed Issues [here](https://github.com/lknknm/REZ-menu-app/issues); +- You can see the Open and Merged Pull Requests with discussion [here](https://github.com/lknknm/REZ-menu-app/pulls). + +### Project Management +We managed the project with GitHub Projects by applying the `Agile/Scrum` methodology. This way we can track issues, assign them to each member of the project group and also track the development status. + +The `Agile/Scrum` methodology was used so the group could discuss the current open issues, understand each problem together and organize new sprints to solve them. Features or bugfixes could be suggested by any member of the group (in an ideal case, we could also include users feedback), as long as they provide clear information about the problems they are encountering during the development process. + +After tracking each issue and organizing them by `Priority`, we add them to the Backlog, assign them to a group member to solve, and track the status during the Sprint. + +![Alt text](./assets/issue-example-2.png) + +![Alt text](./assets/scrumproject.png) + +- You can see the GitHub Projects page with the current development status [here](https://github.com/users/lknknm/projects/1/views/1). +- You can see Open and Closed Issues [here](https://github.com/lknknm/REZ-menu-app/issues); +- You can see the Open and Merged Pull Requests with discussion [here](https://github.com/lknknm/REZ-menu-app/pulls). + +### Hosting +### User Experience +### User Interface Programming +### Safe Programming \ No newline at end of file diff --git a/doc/dev/assets/issue-example-1.png b/doc/dev/assets/issue-example-1.png new file mode 100644 index 0000000..a47d436 Binary files /dev/null and b/doc/dev/assets/issue-example-1.png differ diff --git a/doc/dev/assets/issue-example-2.png b/doc/dev/assets/issue-example-2.png new file mode 100644 index 0000000..1e1e8dd Binary files /dev/null and b/doc/dev/assets/issue-example-2.png differ diff --git a/doc/dev/assets/scrumproject.png b/doc/dev/assets/scrumproject.png new file mode 100644 index 0000000..432938d Binary files /dev/null and b/doc/dev/assets/scrumproject.png differ