Menu
Coddy logo textTech

Adding a New Item

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

challenge icon

Challenge

Easy

Extend your inventory management system by implementing functionality to add new products safely. This challenge builds on the previous stock checking system and adds the ability to expand your inventory while preventing duplicate entries through proper error handling.

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 new products to add in the format "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3" (e.g., "Monitor:299.99:10,Mouse:19.99:20,Webcam:89.99:12")

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 addNewItem that takes the inventory map, product name, price, and quantity as parameters and returns an error:
    • If the product already exists in the inventory, return an error with the message "product already exists: [product_name]"
    • If the product doesn't exist, add it to the inventory and return nil
  7. Parse the second input by splitting on commas to get the list of new products to add
  8. For each new product entry, split on colons to get product name, price, and quantity
  9. Convert the price string to float64 and quantity string to int
  10. Display the addition process header: "Adding New Items:"
  11. For each new product, call the addNewItem function and display the results:
    • If no error: "[product_name]: Successfully added - $[price] (Stock: [quantity])"
    • If error: "[product_name]: Failed to add - [error_message]"
  12. Count and display addition statistics:
    • "Addition Summary:"
    • "Items processed: [total_number_of_items_processed]"
    • "Items added: [number_of_items_successfully_added]"
    • "Items rejected: [number_of_items_that_failed_to_add]"
  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 rejected products:
    • If there are rejected products: "Rejected products: [comma_separated_list_of_rejected_products]"
    • If no rejected products: "All new products were added 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 expand data collections while preventing duplicate entries through proper error handling and validation.

Try it yourself

package main

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

type Product struct {
	Price    float64
	Quantity int
}

func checkStock(inventory map[string]Product, productName string) (int, error) {
	product, exists := inventory[productName]
	if !exists {
		return 0, errors.New("product not found: " + productName)
	}
	return product.Quantity, nil
}

func main() {
	var inventoryData string
	var checkRequests string
	fmt.Scanln(&inventoryData)
	fmt.Scanln(&checkRequests)

	inventory := make(map[string]Product)

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

	// Parse check requests
	productsToCheck := strings.Split(checkRequests, ",")

	fmt.Println("Stock Check Results:")

	var productsFound int
	var productsNotFound int
	var totalStock int
	var missingProducts []string

	for _, productName := range productsToCheck {
		quantity, err := checkStock(inventory, productName)
		if err != nil {
			fmt.Printf("%s: Error - %s\n", productName, err.Error())
			productsNotFound++
			missingProducts = append(missingProducts, productName)
		} else {
			fmt.Printf("%s: %d units in stock\n", productName, quantity)
			productsFound++
			totalStock += quantity
		}
	}

	fmt.Println("Check Summary:")
	fmt.Printf("Products checked: %d\n", len(productsToCheck))
	fmt.Printf("Products found: %d\n", productsFound)
	fmt.Printf("Products not found: %d\n", productsNotFound)
	fmt.Printf("Total stock for found products: %d units\n", totalStock)

	if len(missingProducts) > 0 {
		fmt.Printf("Missing products: %s\n", strings.Join(missingProducts, ","))
	} else {
		fmt.Println("All requested products are available")
	}
}

All lessons in Logic & Flow