Menu
Coddy logo textTech

Putting It All Together

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

challenge icon

Challenge

Easy

Complete your inventory management system by creating a comprehensive main program that integrates all the functionality you've built in previous lessons. This final challenge brings together inventory initialization, stock checking, item addition, stock updates, and report generation into a complete command-line interface with menu-driven navigation.

You will receive three inputs:

  • A string containing initial 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 a sequence of menu operations in the format "operation1,operation2,operation3" where operations can be "check", "add", "update", "report", or "exit" (e.g., "check,add,update,report,exit")
  • A string containing operation parameters in the format "param1|param2|param3" where each parameter corresponds to the operation at the same position (e.g., "Mouse|Monitor:299.99:10|Laptop:5|full,10")

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 and initialize the inventory map with the existing product data
  3. Display the system startup message:
    • "=== INVENTORY MANAGEMENT SYSTEM ==="
    • "System initialized with [number_of_products] products"
    • "Starting interactive session..."
  4. Parse the second input to get the sequence of operations to perform
  5. Parse the third input to get the parameters for each operation
  6. For each operation in sequence, display the operation header and perform the corresponding action:
    • For "check": Display "--- STOCK CHECK ---" and check stock for the specified product
    • For "add": Display "--- ADD ITEM ---" and add the specified product
    • For "update": Display "--- UPDATE STOCK ---" and update stock for the specified product
    • For "report": Display "--- GENERATE REPORT ---" and generate the specified report
    • For "exit": Display "--- SYSTEM EXIT ---" and show exit information
  7. Implement the checkStock function that returns quantity and error as in previous lessons
  8. Implement the addNewItem function that adds products and returns error as in previous lessons
  9. Implement the updateStock function that updates quantities and returns error as in previous lessons
  10. Implement the generateReport function that creates reports as in previous lessons
  11. For the "check" operation:
    • Use the parameter as the product name to check
    • Display: "Checking stock for: [product_name]"
    • If found: "Stock level: [quantity] units"
    • If not found: "Product not found in inventory"
  12. For the "add" operation:
    • Parse the parameter in format "product_name:price:quantity"
    • Display: "Adding new product: [product_name]"
    • If successful: "Product added successfully"
    • If failed: "Failed to add product: [error_message]"
  13. For the "update" operation:
    • Parse the parameter in format "product_name:change"
    • Display: "Updating stock for: [product_name]"
    • If successful and change is positive: "Added [change] units. New stock: [new_quantity]"
    • If successful and change is negative: "Removed [absolute_change] units. New stock: [new_quantity]"
    • If failed: "Update failed: [error_message]"
  14. For the "report" operation:
    • Parse the parameter in format "report_type,threshold"
    • Display: "Generating [report_type] report with threshold [threshold]"
    • Generate and display the full report as in previous lessons
  15. For the "exit" operation:
    • Display final inventory statistics:
      • "Final inventory status:"
      • "Total products: [total_products]"
      • "Total items: [total_items]"
      • "Total value: $[total_value]"
    • Display: "Session completed successfully"
    • Display: "Thank you for using the Inventory Management System"
  16. After each operation (except exit), display: "Operation completed. Continuing to next operation..."

Use the strings package to split input strings, the strconv package to convert strings to numbers, the errors package for error handling, the fmt package for formatted output, and the sort package for alphabetical sorting. Format all prices and values to 2 decimal places. This challenge demonstrates how to create a complete interactive system that integrates multiple functional components into a cohesive user experience with proper error handling and state management.

Try it yourself

package main

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

type Product struct {
	Price    float64
	Quantity int
}

func generateReport(inventory map[string]Product, reportType string, threshold float64) {
	// Display report header
	switch reportType {
	case "full":
		fmt.Println("=== FULL INVENTORY REPORT ===")
	case "low_stock":
		fmt.Println("=== LOW STOCK REPORT ===")
	case "high_value":
		fmt.Println("=== HIGH VALUE REPORT ===")
	}

	// Calculate general statistics
	totalProducts := len(inventory)
	totalItems := 0
	totalValue := 0.0
	
	for _, product := range inventory {
		totalItems += product.Quantity
		totalValue += product.Price * float64(product.Quantity)
	}
	
	averagePrice := totalValue / float64(totalItems)

	// Display general 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)
	fmt.Printf("Average Product Price: $%.2f\n", averagePrice)

	// Filter products based on report type
	var filteredProducts []string
	for name, product := range inventory {
		switch reportType {
		case "full":
			filteredProducts = append(filteredProducts, name)
		case "low_stock":
			if product.Quantity <= int(threshold) {
				filteredProducts = append(filteredProducts, name)
			}
		case "high_value":
			productValue := product.Price * float64(product.Quantity)
			if productValue >= threshold {
				filteredProducts = append(filteredProducts, name)
			}
		}
	}

	// Sort filtered products alphabetically
	sort.Strings(filteredProducts)

	// Display filtered products section header
	switch reportType {
	case "full":
		fmt.Println("All Products:")
	case "low_stock":
		fmt.Printf("Products with stock ≤ %.0f:\n", threshold)
	case "high_value":
		fmt.Printf("Products with value ≥ $%.2f:\n", threshold)
	}

	// Display filtered products
	filteredItems := 0
	filteredValue := 0.0
	for _, name := range filteredProducts {
		product := inventory[name]
		productValue := product.Price * float64(product.Quantity)
		fmt.Printf("- %s: $%.2f × %d = $%.2f\n", name, product.Price, product.Quantity, productValue)
		filteredItems += product.Quantity
		filteredValue += productValue
	}

	// Display filtered statistics
	fmt.Println("Filtered Results:")
	fmt.Printf("Products shown: %d\n", len(filteredProducts))
	fmt.Printf("Items in filtered products: %d\n", filteredItems)
	fmt.Printf("Value of filtered products: $%.2f\n", filteredValue)

	// Find most and least expensive products
	var mostExpensiveName, leastExpensiveName string
	var mostExpensivePrice, leastExpensivePrice float64
	first := true
	
	var sortedNames []string
	for name := range inventory {
		sortedNames = append(sortedNames, name)
	}
	sort.Strings(sortedNames)
	
	for _, name := range sortedNames {
		product := inventory[name]
		if first {
			mostExpensiveName = name
			mostExpensivePrice = product.Price
			leastExpensiveName = name
			leastExpensivePrice = product.Price
			first = false
		} else {
			if product.Price > mostExpensivePrice {
				mostExpensiveName = name
				mostExpensivePrice = product.Price
			}
			if product.Price < leastExpensivePrice {
				leastExpensiveName = name
				leastExpensivePrice = product.Price
			}
		}
	}

	fmt.Println("Price Analysis:")
	fmt.Printf("Most expensive: %s at $%.2f\n", mostExpensiveName, mostExpensivePrice)
	fmt.Printf("Least expensive: %s at $%.2f\n", leastExpensiveName, leastExpensivePrice)

	// Find highest and lowest stock products
	var highestStockName, lowestStockName string
	var highestStock, lowestStock int
	first = true
	
	for _, name := range sortedNames {
		product := inventory[name]
		if first {
			highestStockName = name
			highestStock = product.Quantity
			lowestStockName = name
			lowestStock = product.Quantity
			first = false
		} else {
			if product.Quantity > highestStock {
				highestStockName = name
				highestStock = product.Quantity
			}
			if product.Quantity < lowestStock {
				lowestStockName = name
				lowestStock = product.Quantity
			}
		}
	}

	fmt.Println("Stock Analysis:")
	fmt.Printf("Highest stock: %s with %d units\n", highestStockName, highestStock)
	fmt.Printf("Lowest stock: %s with %d units\n", lowestStockName, lowestStock)

	// Inventory health assessment
	lowStockCount := 0
	highStockCount := 0
	highValueCount := 0
	
	for _, product := range inventory {
		if product.Quantity <= 5 {
			lowStockCount++
		}
		if product.Quantity > 20 {
			highStockCount++
		}
		productValue := product.Price * float64(product.Quantity)
		if productValue >= 500.0 {
			highValueCount++
		}
	}

	fmt.Printf("Low stock items (≤5): %d\n", lowStockCount)
	fmt.Printf("High stock items (>20): %d\n", highStockCount)
	fmt.Printf("High value items (≥$500): %d\n", highValueCount)

	// Report completion
	fmt.Println("Report generated successfully")
	fmt.Printf("Threshold applied: %.2f\n", threshold)
}

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

	// Parse inventory data
	inventory := make(map[string]Product)
	if inventoryData != "" {
		products := strings.Split(inventoryData, ",")
		for _, productStr := range products {
			parts := strings.Split(productStr, ":")
			name := parts[0]
			price, _ := strconv.ParseFloat(parts[1], 64)
			quantity, _ := strconv.Atoi(parts[2])
			inventory[name] = Product{Price: price, Quantity: quantity}
		}
	}

	// Parse report configuration
	configParts := strings.Split(reportConfig, ",")
	reportType := configParts[0]
	threshold, _ := strconv.ParseFloat(configParts[1], 64)

	// Generate report
	generateReport(inventory, reportType, threshold)
}

All lessons in Logic & Flow