Menu
Coddy logo textTech

Updating Stock Quantity

Part of the Logic & Flow section of Coddy's GO journey — lesson 48 of 68.

challenge icon

Challenge

Easy

Enhance your inventory management system by implementing stock quantity updates with comprehensive validation and error handling. This challenge builds on the previous functionality and adds the ability to modify existing product quantities while preventing invalid operations that could result in negative stock levels.

You will receive two inputs:

  • A string containing existing inventory data in the format "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3" (e.g., "Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8")
  • A string containing stock update requests in the format "product1:change1,product2:change2,product3:change3" where changes can be positive or negative integers (e.g., "Mouse:10,Tablet:-5,Keyboard:-3")

Your task is to:

  1. Use the same Product struct from previous lessons with Price (float64) and Quantity (int) fields
  2. Parse the first input by splitting on commas to get individual existing product entries
  3. For each existing product entry, split on colons to get product name, price, and quantity
  4. Convert the price string to float64 and quantity string to int
  5. Create and populate the inventory map with the existing product data
  6. Create a function called updateStock that takes the inventory map, product name, and quantity change as parameters and returns an error:
    • If the product doesn't exist in the inventory, return an error with the message "product not found: [product_name]"
    • If the quantity change would result in a negative stock (current quantity + change < 0), return an error with the message "insufficient stock: cannot reduce [product_name] by [absolute_change_value], only [current_quantity] available"
    • If the update is valid, modify the product's quantity in the inventory and return nil
  7. Parse the second input by splitting on commas to get the list of stock update requests
  8. For each update request, split on colons to get product name and quantity change
  9. Convert the quantity change string to int
  10. Display the update process header: "Processing Stock Updates:"
  11. For each update request, call the updateStock function and display the results:
    • If no error and change is positive: "[product_name]: Added [change] units - New stock: [new_quantity]"
    • If no error and change is negative: "[product_name]: Removed [absolute_change_value] units - New stock: [new_quantity]"
    • If no error and change is zero: "[product_name]: No change - Current stock: [current_quantity]"
    • If error: "[product_name]: Update failed - [error_message]"
  12. Count and display update statistics:
    • "Update Summary:"
    • "Updates processed: [total_number_of_updates_processed]"
    • "Updates successful: [number_of_successful_updates]"
    • "Updates failed: [number_of_failed_updates]"
  13. Display the updated inventory in alphabetical order by product name:
    • "Updated Inventory:"
    • For each product: "- [product_name]: $[price] (Stock: [quantity])"
  14. Calculate and display final inventory statistics:
    • "Final Inventory Statistics:"
    • "Total Products: [total_number_of_products_in_inventory]"
    • "Total Items in Stock: [sum_of_all_quantities]"
    • "Total Inventory Value: $[sum_of_price_times_quantity_for_all_products]"
  15. List any failed updates:
    • If there are failed updates: "Failed updates: [comma_separated_list_of_failed_product_names]"
    • If no failed updates: "All stock updates were processed successfully"

Use the strings package to split the input strings, the strconv package to convert strings to numbers, the errors package to create error messages, the fmt package for formatted output, and the sort package to sort product names alphabetically. Format all prices to 2 decimal places and the total inventory value to 2 decimal places. This challenge demonstrates how to safely modify existing data while preventing invalid operations through comprehensive validation and error handling.

Try it yourself

package main

import (
	"errors"
	"fmt"
	"sort"
	"strconv"
	"strings"
)

type Product struct {
	Price    float64
	Quantity int
}

func addNewItem(inventory map[string]Product, productName string, price float64, quantity int) error {
	if _, exists := inventory[productName]; exists {
		return errors.New("product already exists: " + productName)
	}
	inventory[productName] = Product{Price: price, Quantity: quantity}
	return nil
}

func main() {
	var existingInventory string
	var newProducts string
	fmt.Scanln(&existingInventory)
	fmt.Scanln(&newProducts)

	inventory := make(map[string]Product)

	// Parse existing inventory
	existingItems := strings.Split(existingInventory, ",")
	for _, item := range existingItems {
		parts := strings.Split(item, ":")
		name := parts[0]
		price, _ := strconv.ParseFloat(parts[1], 64)
		quantity, _ := strconv.Atoi(parts[2])
		inventory[name] = Product{Price: price, Quantity: quantity}
	}

	// Parse new products to add
	newItems := strings.Split(newProducts, ",")
	
	fmt.Println("Adding New Items:")
	
	itemsProcessed := 0
	itemsAdded := 0
	itemsRejected := 0
	var rejectedProducts []string

	for _, item := range newItems {
		parts := strings.Split(item, ":")
		name := parts[0]
		price, _ := strconv.ParseFloat(parts[1], 64)
		quantity, _ := strconv.Atoi(parts[2])
		
		itemsProcessed++
		
		err := addNewItem(inventory, name, price, quantity)
		if err != nil {
			fmt.Printf("%s: Failed to add - %s\n", name, err.Error())
			itemsRejected++
			rejectedProducts = append(rejectedProducts, name)
		} else {
			fmt.Printf("%s: Successfully added - $%.2f (Stock: %d)\n", name, price, quantity)
			itemsAdded++
		}
	}

	// Addition summary
	fmt.Println("Addition Summary:")
	fmt.Printf("Items processed: %d\n", itemsProcessed)
	fmt.Printf("Items added: %d\n", itemsAdded)
	fmt.Printf("Items rejected: %d\n", itemsRejected)

	// Display updated inventory in alphabetical order
	fmt.Println("Updated Inventory:")
	var productNames []string
	for name := range inventory {
		productNames = append(productNames, name)
	}
	sort.Strings(productNames)

	totalProducts := 0
	totalItems := 0
	totalValue := 0.0

	for _, name := range productNames {
		product := inventory[name]
		fmt.Printf("- %s: $%.2f (Stock: %d)\n", name, product.Price, product.Quantity)
		totalProducts++
		totalItems += product.Quantity
		totalValue += product.Price * float64(product.Quantity)
	}

	// Final inventory statistics
	fmt.Println("Final Inventory Statistics:")
	fmt.Printf("Total Products: %d\n", totalProducts)
	fmt.Printf("Total Items in Stock: %d\n", totalItems)
	fmt.Printf("Total Inventory Value: $%.2f\n", totalValue)

	// List rejected products
	if len(rejectedProducts) > 0 {
		fmt.Printf("Rejected products: %s\n", strings.Join(rejectedProducts, ","))
	} else {
		fmt.Println("All new products were added successfully")
	}
}

All lessons in Logic & Flow