/// <summary>
        /// Validate Product form data
        /// </summary>
        private async Task ValidateProductFormData(Product product, Product dbProduct = null)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            if (string.IsNullOrEmpty(product.Name))
            {
                errorsList.AddError("Name", Phrases.GlobalRequiredField);
            }

            if (string.IsNullOrEmpty(product.Reference))
            {
                errorsList.AddError("Reference", Phrases.GlobalRequiredField);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // Check if the reference already exist This validation only occurs when all form fields
            // have no errors And only if is a create or an update and the reference has changed
            Product nameCheck = ((dbProduct == null) || (dbProduct.Reference != product.Reference))
              ? await _repository.Products.FindOneAsync(p => p.Reference.ToLower() == product.Reference.ToLower())
              : null;

            if (nameCheck != null)
            {
                errorsList.AddError("Reference", Phrases.ProductErrorReference);

                throw new OperationErrorException(errorsList);
            }
        }
        private async Task ValidateProductLocationDataAsync(ProductLocation productLocation)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            if (productLocation.LocationId <= 0)
            {
                errorsList.AddError("LocationId", Phrases.GlobalRequiredField);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // check if the product is already associated with the location
            ProductLocation pLocationCheck = await _repository.ProductLocations
                                             .FindOneAsync(pl => pl.ProductId == productLocation.ProductId && pl.LocationId == productLocation.LocationId);

            if (pLocationCheck != null)
            {
                errorsList.AddError("LocationId", Phrases.ProductLocationErrorAlreadyAssociated);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }
        }
        public async Task DeleteAsync(int[] productIds)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            try
            {
                for (int i = 0; i < productIds.Length; i += 1)
                {
                    int productId = productIds[i];

                    Product product = await _repository.Products.GetByIdAsync(productId);

                    if (product != null)
                    {
                        _repository.Products.Remove(product);
                    }
                }

                await _repository.SaveChangesAsync();
            }
            catch
            {
                errorsList.AddError("delete-product-db-error", Phrases.GlobalErrorOperationDB);

                throw new ServiceErrorException(errorsList);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Validate Location form data
        /// </summary>
        private async Task ValidateLocationFormData(Location location, Location dbLocation = null)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            if (string.IsNullOrEmpty(location.Name))
            {
                errorsList.AddError("Name", Phrases.GlobalRequiredField);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // Check if the name already exist This validation only occurs when all form fields have
            // no errors And only if is a create or an update and the name has changed
            Location nameCheck = ((dbLocation == null) || (dbLocation.Name != location.Name))
              ? await _repository.Locations.FindOneAsync(x => x.Name.ToLower() == location.Name.ToLower())
              : null;

            if (nameCheck != null)
            {
                errorsList.AddError("Name", Phrases.LocationErrorName);

                throw new OperationErrorException(errorsList);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Validate User form data
        /// </summary>
        private async Task ValidateUserFormDataAsync(User user, User dbUser = null)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            if (string.IsNullOrEmpty(user.Username))
            {
                errorsList.AddError("Username", Phrases.GlobalRequiredField);
            }

            if ((dbUser == null) && string.IsNullOrEmpty(user.Password))
            {
                errorsList.AddError("Password", Phrases.GlobalRequiredField);
            }

            // Validate the form values
            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // Check if the username already exist This validation only occurs when all form fields
            // have no errors And only if is a create or an update and the username has changed
            User usernameCheck = ((dbUser == null) || (dbUser.Username != user.Username))
              ? await _repository.Users.FindOneWithRoleAsync(u => u.Username.ToLower() == user.Username.ToLower())
              : null;

            if (usernameCheck != null)
            {
                errorsList.AddError("Username", Phrases.UserErrorUsername);

                throw new OperationErrorException(errorsList);
            }
        }
Beispiel #6
0
        public async Task DeleteAsync(int[] locationIds, int userId)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            try
            {
                for (int i = 0; i < locationIds.Length; i += 1)
                {
                    int locationId = locationIds[i];

                    Location location = await _repository.Locations.GetByIdAsync(locationId);

                    if (location != null)
                    {
                        // If it is the main location cannot be deleted
                        if (location.IsMain)
                        {
                            errorsList.AddError(
                                "MainLocation",
                                Phrases.LocationErrorMainLocation
                                );

                            throw new OperationErrorException(errorsList);
                        }

                        // Iterate through the productLocations and move the stock to the main
                        // location before remove the location
                        if ((location.ProductLocations != null) && location.ProductLocations.Any())
                        {
                            while (location.ProductLocations.Any())
                            {
                                ProductLocation producLocation = location.ProductLocations.ElementAt(0);

                                // Remove the ProductLocation association and move the stock
                                await AppServices.ProductLocationService
                                .DeleteAsyn(producLocation.ProductLocationId, userId);
                            }
                        }

                        _repository.Locations.Remove(location);
                    }
                }

                await _repository.SaveChangesAsync();
            }
            catch (OperationErrorException operationErrorException)
            {
                // Catch operation errors
                throw operationErrorException;
            }
            catch
            {
                // catch other errors and send a Service Error Exception
                errorsList.AddError("delete-location-db-error", Phrases.GlobalErrorOperationDB);

                throw new ServiceErrorException(errorsList);
            }
        }
        private void VerifyIfHasStockAvailableToMove(ProductLocation plocation, float qty, string field = "qty")
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            if (plocation.Stock < qty)
            {
                errorsList.AddError(field, Phrases.StockMovementErrorQty);
                throw new OperationErrorException(errorsList);
            }
        }
        public async Task ExportNotificationsToPDFAsync(IEnumerable <Notification> notifications)
        {
            try
            {
                PDFGenerator pdf     = new PDFGenerator(Phrases.GlobalStockAlerts, Phrases.StockAlertsListOf);
                Section      section = pdf.CreateDocumentSection();

                // Set title
                pdf.AddParagraph(Phrases.GlobalStockAlerts, true, false, 16);
                pdf.AddParagraph($"{Phrases.GlobalDate}: {DateTime.Now.ShortDate()}", false, true, null, 1);

                // Create table and table columns
                Table table = pdf.CreateTable();
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Right);
                pdf.AddTableColumn(table, ParagraphAlignment.Right);

                // Create table header
                Row row = pdf.CreateTableHeaderRow(table);
                pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, Phrases.GlobalDate, true);
                pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, Phrases.GlobalReference, true);
                pdf.AddTableRowCell(row, 2, ParagraphAlignment.Left, Phrases.GlobalProduct, true);
                pdf.AddTableRowCell(row, 3, ParagraphAlignment.Left, Phrases.GlobalLocation, true);
                pdf.AddTableRowCell(row, 4, ParagraphAlignment.Right, Phrases.StockMovementMinStock, true);
                pdf.AddTableRowCell(row, 5, ParagraphAlignment.Right, Phrases.StockMovementsStock, true);

                // Populate the table rows
                notifications.ToList().ForEach((notification) => {
                    row = table.AddRow();
                    pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, notification.CreatedAt.ShortDateWithTime());
                    pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, notification.ProductLocation.Product.Reference);
                    pdf.AddTableRowCell(row, 2, ParagraphAlignment.Left, notification.ProductLocation.Product.Name);
                    pdf.AddTableRowCell(row, 3, ParagraphAlignment.Left, notification.ProductLocation.Location.Name);
                    pdf.AddTableRowCell(row, 4, ParagraphAlignment.Right, notification.ProductLocation.Stock.ToString());
                    pdf.AddTableRowCell(row, 5, ParagraphAlignment.Right, notification.ProductLocation.MinStock.ToString());
                });

                // Add the table to the section
                pdf.AddTableToLastSection(table);

                // Rendering the document
                await pdf.GenerateAsync();
            }
            catch
            {
                OperationErrorsList errorsList = new OperationErrorsList();
                errorsList.AddError("export-notifications-error", Phrases.GlobalErrorOperationDB);
                throw new ServiceErrorException(errorsList);
            }
        }
        public async Task ExportProductLocationsFromLocationToPDFAsync(IEnumerable <ProductLocation> productLocations)
        {
            try
            {
                string       locationName = productLocations.ElementAt(0).Location.Name;
                PDFGenerator pdf          = new PDFGenerator($"{Phrases.GlobalProducts} {locationName}", Phrases.ProductsListOf);
                Section      section      = pdf.CreateDocumentSection();

                // Set title
                pdf.AddParagraph(Phrases.GlobalProducts, true, false, 16);
                pdf.AddParagraph($"{Phrases.GlobalDate}: {DateTime.Now.ShortDate()}", false, true);
                pdf.AddParagraph($"{Phrases.GlobalLocation}: {locationName}", false, true, null, 1);

                // Create table and table columns
                Table table = pdf.CreateTable();
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Right);

                // Create table header
                Row row = pdf.CreateTableHeaderRow(table);
                pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, Phrases.GlobalReference, true);
                pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, Phrases.GlobalName, true);
                pdf.AddTableRowCell(row, 2, ParagraphAlignment.Right, Phrases.StockMovementsStock, true);

                // Populate the table rows
                productLocations.ToList().ForEach((productLocation) => {
                    row = table.AddRow();
                    pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, productLocation.Product.Reference);
                    pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, productLocation.Product.Name);
                    pdf.AddTableRowCell(row, 2, ParagraphAlignment.Right, productLocation.Stock.ToString());
                });

                // Add the table to the section
                pdf.AddTableToLastSection(table);

                // Rendering the document
                await pdf.GenerateAsync();
            }
            catch
            {
                OperationErrorsList errorsList = new OperationErrorsList();
                errorsList.AddError("export-location-products-error", Phrases.GlobalErrorOperationDB);
                throw new ServiceErrorException(errorsList);
            }
        }
        public async Task CreateAsync(StockMovement data, bool applyDbChanges = false)
        {
            try
            {
                int locationId = ( int )((data.ToLocationId != null)
                  ? data.ToLocationId
                  : data.FromLocationId);

                ProductLocation productLocation = await AppServices.ProductLocationService
                                                  .GetOneAsync(data.ProductId, locationId);

                // Calculate the new accumulated stock
                if (productLocation != null)
                {
                    data.Stock = (productLocation.Stock + data.Qty);

                    await AppServices.NotificationService.ToggleStockAlertsAsync(productLocation, data.Stock);
                }
                else
                {
                    // Set the accumulated if it is the first movement
                    data.Stock = data.Qty;
                }

                await _repository.StockMovements.AddAsync(data);

                // Normally this service is called inside other services and the call of the
                // SaveChangesAsync method it will be the responsibility of the other service. In
                // some circumstances we want the apply the db changes after create the stock
                // movement, for that we need to sent the applyDbChanges setted to true.
                if (applyDbChanges)
                {
                    await _repository.SaveChangesAsync();
                }
            }
            catch
            {
                OperationErrorsList errorsList = new OperationErrorsList();
                errorsList.AddError("add-stock-movement-db-error", Phrases.GlobalErrorOperationDB);

                throw new ServiceErrorException(errorsList);
            }
        }
Beispiel #11
0
        public async Task DeleteAsync(int[] userIds, int loggedInUserId)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            try
            {
                // You can't delete yourself
                if (userIds.Contains(loggedInUserId))
                {
                    errorsList.AddError("LoggedInUserId", Phrases.UserErrorDeleteYourself);

                    throw new OperationErrorException(errorsList);
                }

                for (int i = 0; i < userIds.Length; i += 1)
                {
                    int userId = userIds[i];

                    User user = await _repository.Users.GetByIdWithRoleAsync(userId);

                    if (user != null)
                    {
                        _repository.Users.Remove(user);
                    }
                }

                await _repository.SaveChangesAsync();

                // Catch operation errors
            }
            catch (OperationErrorException operationErrorException)
            {
                throw operationErrorException;

                // catch other errors and send a Service Error Exception
            }
            catch
            {
                errorsList.AddError("delete-user-db-error", Phrases.GlobalErrorOperationDB);

                throw new ServiceErrorException(errorsList);
            }
        }
        public async Task UpdateMinStock(int productLocation, float minStock)
        {
            try
            {
                ProductLocation dbProductLocation = await _repository.ProductLocations.GetByIdAsync(productLocation);

                dbProductLocation.MinStock = minStock;

                await AppServices.NotificationService.ToggleStockAlertsAsync(dbProductLocation, dbProductLocation.Stock);

                await _repository.SaveChangesAsync();
            }
            catch
            {
                // catch service errors
                OperationErrorsList errorsList = new OperationErrorsList();
                errorsList.AddError("remove-product-location-db-error", Phrases.GlobalErrorOperationDB);
                throw new ServiceErrorException(errorsList);
            }
        }
Beispiel #13
0
        public async Task UpdateAppSettingsAsync(AppSettings data)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            try
            {
                AppSettings appSettings = await _repository.AppSettings.GetByIdAsync(data.AppSettingsId);

                appSettings.DocumentsFolder       = data.DocumentsFolder;
                appSettings.Language              = data.Language;
                appSettings.DefaultGlobalMinStock = data.DefaultGlobalMinStock;

                await _repository.SaveChangesAsync();
            }
            catch
            {
                errorsList.AddError("update-settings-db-error", Phrases.GlobalErrorOperationDB);

                throw new ServiceErrorException(errorsList);
            }
        }
Beispiel #14
0
        public async Task <User> AuthenticateAsync(string username, string password)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            // Validate data
            if (string.IsNullOrEmpty(username))
            {
                errorsList.AddError("Username", Phrases.GlobalRequiredField);
            }

            if (string.IsNullOrEmpty(password))
            {
                errorsList.AddError("Password", Phrases.GlobalRequiredField);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // get the user from the DB
            User user = await _repository.Users.FindOneWithRoleAsync(u => u.Username.ToLower() == username.ToLower());

            // If the user exist and the password are match, it's all good.
            if (user != null && BCrypt.Net.BCrypt.Verify(password, user.Password))
            {
                // Set the last login data
                user.LastLogin = DateTime.UtcNow;
                await _repository.SaveChangesAsync();
            }
            else
            {
                errorsList.AddError("Generic", Phrases.UserErrorLogin);

                throw new OperationErrorException(errorsList);
            }

            return(user);
        }
        public async Task DeleteAsyn(int productLocationId, int userId)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            try
            {
                ProductLocation productLocation = await _repository.ProductLocations.GetByIdAsync(productLocationId);

                if (productLocation != null)
                {
                    // Cannot remove the association with the main location
                    if (productLocation.Location.IsMain)
                    {
                        errorsList.AddError("LocationId", Phrases.ProductLocationDeleteErrorMainLocation);
                        throw new OperationErrorException(errorsList);
                    }

                    // Move the stock back to the main location, if any.
                    await AppServices.StockMovementService.MoveStockToMainLocationAsync(productLocation, userId);

                    // Remove the location
                    _repository.ProductLocations.Remove(productLocation);
                    await _repository.SaveChangesAsync();
                }
            }
            catch (OperationErrorException operationErrorException)
            {
                // catch operations errors
                throw operationErrorException;
            }
            catch
            {
                // catch service errors
                errorsList.AddError("remove-product-location-db-error", Phrases.GlobalErrorOperationDB);
                throw new ServiceErrorException(errorsList);
            }
        }
Beispiel #16
0
        public async Task ChangePasswordAsync(int userId, string currentPassword, string newPassword)
        {
            OperationErrorsList errorsList = new OperationErrorsList();

            // Validate data
            if (string.IsNullOrEmpty(currentPassword))
            {
                errorsList.AddError("CurrentPassword", Phrases.GlobalRequiredField);
            }

            if (string.IsNullOrEmpty(newPassword))
            {
                errorsList.AddError("NewPassword", Phrases.GlobalRequiredField);
            }

            if (errorsList.HasErrors())
            {
                throw new OperationErrorException(errorsList);
            }

            // Get the user to verify the current password
            User dbUser = await _repository.Users.GetByIdWithRoleAsync(userId);

            if ((dbUser != null) && BCrypt.Net.BCrypt.Verify(currentPassword, dbUser.Password))
            {
                // Encrypt password
                dbUser.Password = BCrypt.Net.BCrypt.HashPassword(newPassword);
                await _repository.SaveChangesAsync();
            }
            else
            {
                errorsList.AddError("CurrentPassword", Phrases.UserErrorInvalidPassword);

                throw new OperationErrorException(errorsList);
            }
        }
        public async Task ExportStockMovementsToPDFAsync(ExportData <IEnumerable <StockMovement>, StockMovementOptions> data)
        {
            try
            {
                IEnumerable <StockMovement> movements = data.Data;
                StockMovementOptions        options   = data?.Options;

                PDFGenerator pdf     = new PDFGenerator(Phrases.StockMovementsLabel, Phrases.StockMovementsListOf);
                Section      section = pdf.CreateDocumentSection();

                // Set title
                pdf.AddParagraph(Phrases.StockMovementsLabel, true, false, 16);

                if (options != null)
                {
                    string startDate = (options?.StartDate != default)
                        ? $"{options.StartDate.ShortDate()} - "
                        : "";

                    string endDate = (options?.EndDate != default)
                        ? options.EndDate.ShortDate()
                        : "";

                    pdf.AddParagraph($"{Phrases.GlobalDate}: {startDate}{endDate}", false, true);

                    if (!string.IsNullOrEmpty(options.SearchValue))
                    {
                        Product product = movements.ElementAt(0).Product;
                        pdf.AddParagraph($"{Phrases.GlobalProduct}: {product.Reference} {product.Name}", false, true);
                    }

                    if (options.LocationId != null)
                    {
                        Location location = await AppServices.LocationService.GetByIdAsync(( int )options.LocationId);

                        pdf.AddParagraph($"{Phrases.GlobalLocation}: {location.Name}", false, true);
                    }


                    if (options.UserId != null)
                    {
                        User user = await AppServices.UserService.GetByIdAsync(( int )options.UserId);

                        pdf.AddParagraph($"{Phrases.GlobalUser}: {user.Username}", false, true);
                    }

                    pdf.AddParagraph("", false, false, null, 1);
                }

                // Create table and table columns
                Table table = pdf.CreateTable();
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Left);
                pdf.AddTableColumn(table, ParagraphAlignment.Right);
                pdf.AddTableColumn(table, ParagraphAlignment.Right);

                // Create table header
                Row row = pdf.CreateTableHeaderRow(table);
                pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, Phrases.GlobalDate, true);
                pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, Phrases.GlobalUser, true);
                pdf.AddTableRowCell(row, 2, ParagraphAlignment.Left, Phrases.GlobalReference, true);
                pdf.AddTableRowCell(row, 3, ParagraphAlignment.Left, Phrases.GlobalName, true);
                pdf.AddTableRowCell(row, 4, ParagraphAlignment.Left, Phrases.GlobalMovement, true);
                pdf.AddTableRowCell(row, 5, ParagraphAlignment.Right, Phrases.StockMovementQty, true);
                pdf.AddTableRowCell(row, 6, ParagraphAlignment.Right, Phrases.StockMovementStockAcc, true);

                // Populate the table rows
                movements.ToList().ForEach((movement) => {
                    row = table.AddRow();
                    pdf.AddTableRowCell(row, 0, ParagraphAlignment.Left, movement.CreatedAt.ShortDateWithTime());
                    pdf.AddTableRowCell(row, 1, ParagraphAlignment.Left, movement.User.Username);
                    pdf.AddTableRowCell(row, 2, ParagraphAlignment.Left, movement.Product.Reference);
                    pdf.AddTableRowCell(row, 3, ParagraphAlignment.Left, movement.Product.Name);
                    pdf.AddTableRowCell(row, 4, ParagraphAlignment.Left, movement.ConcatMovementString());
                    pdf.AddTableRowCell(row, 5, ParagraphAlignment.Right, movement.Qty.ToString());
                    pdf.AddTableRowCell(row, 6, ParagraphAlignment.Right, movement.Stock.ToString());
                });

                // Add the table to the section
                pdf.AddTableToLastSection(table);

                // Rendering the document
                await pdf.GenerateAsync();
            }
            catch
            {
                OperationErrorsList errorsList = new OperationErrorsList();
                errorsList.AddError("export-stock-movements-error", Phrases.GlobalErrorOperationDB);
                throw new ServiceErrorException(errorsList);
            }
        }