Menu
Coddy logo textTech

Generating a Report

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

challenge icon

Challenge

Easy

Complete your inventory management system by implementing a comprehensive reporting function that provides detailed insights into your current inventory. This challenge builds on all previous functionality and adds the ability to generate formatted reports with statistics, categorization, and analysis.

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 report configuration in the format "report_type,threshold_value" where report_type can be "full", "low_stock", or "high_value" and threshold_value is a number (e.g., "low_stock,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 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 generateReport that takes the inventory map, report type, and threshold value as parameters
  7. Parse the second input by splitting on commas to get report type and threshold value
  8. Convert the threshold value string to float64
  9. Display the report header based on the report type:
    • For "full": "=== FULL INVENTORY REPORT ==="
    • For "low_stock": "=== LOW STOCK REPORT ==="
    • For "high_value": "=== HIGH VALUE REPORT ==="
  10. Display general inventory statistics:
    • "Total Products: [total_number_of_products]"
    • "Total Items in Stock: [sum_of_all_quantities]"
    • "Total Inventory Value: $[sum_of_price_times_quantity_for_all_products]"
    • "Average Product Price: $[total_inventory_value_divided_by_total_items]"
  11. Filter and display products based on report type:
    • For "full": Show all products
    • For "low_stock": Show only products with quantity less than or equal to threshold value
    • For "high_value": Show only products with total value (price × quantity) greater than or equal to threshold value
  12. Display the filtered products section:
    • For "full": "All Products:"
    • For "low_stock": "Products with stock ≤ [threshold_value]:"
    • For "high_value": "Products with value ≥ $[threshold_value]:"
  13. For each filtered product (in alphabetical order by product name):
    • "- [product_name]: $[price] × [quantity] = $[total_value]"
  14. Display filtered statistics:
    • "Filtered Results:"
    • "Products shown: [number_of_products_in_filtered_results]"
    • "Items in filtered products: [sum_of_quantities_for_filtered_products]"
    • "Value of filtered products: $[sum_of_values_for_filtered_products]"
  15. Find and display the most expensive and least expensive products:
    • "Price Analysis:"
    • "Most expensive: [product_name] at $[price]"
    • "Least expensive: [product_name] at $[price]"
  16. Find and display the highest and lowest stock products:
    • "Stock Analysis:"
    • "Highest stock: [product_name] with [quantity] units"
    • "Lowest stock: [product_name] with [quantity] units"
  17. Display inventory health assessment:
    • Count products with quantity ≤ 5: "Low stock items (≤5): [count]"
    • Count products with quantity > 20: "High stock items (>20): [count]"
    • Count products with value ≥ $500: "High value items (≥$500): [count]"
  18. Display report completion:
    • "Report generated successfully"
    • "Threshold applied: [threshold_value]"

Use the strings package to split the input strings, the strconv package to convert strings to numbers, the fmt package for formatted output, and the sort package to sort product names alphabetically. Format all prices and values to 2 decimal places. When finding most/least expensive or highest/lowest stock, if there are ties, use the alphabetically first product name. This challenge demonstrates how to create comprehensive reporting systems that provide valuable business insights through data analysis and formatted presentation.

Try it yourself

package main

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

type Product struct {
	Price    float64
	Quantity int
}

func updateStock(inventory map[string]Product, productName string, change int) error {
	product, exists := inventory[productName]
	if !exists {
		return errors.New("product not found: " + productName)
	}
	
	newQuantity := product.Quantity + change
	if newQuantity < 0 {
		return fmt.Errorf("insufficient stock: cannot reduce %s by %d, only %d available", productName, -change, product.Quantity)
	}
	
	product.Quantity = newQuantity
	inventory[productName] = product
	return nil
}

func main() {
	var inventoryData string
	var updateRequests string
	fmt.Scanln(&inventoryData)
	fmt.Scanln(&updateRequests)
	
	// Parse existing inventory
	inventory := make(map[string]Product)
	inventoryEntries := strings.Split(inventoryData, ",")
	
	for _, entry := range inventoryEntries {
		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 update requests
	updateEntries := strings.Split(updateRequests, ",")
	
	fmt.Println("Processing Stock Updates:")
	
	totalUpdates := len(updateEntries)
	successfulUpdates := 0
	failedUpdates := 0
	var failedProducts []string
	
	for _, update := range updateEntries {
		parts := strings.Split(update, ":")
		productName := parts[0]
		change, _ := strconv.Atoi(parts[1])
		
		err := updateStock(inventory, productName, change)
		if err != nil {
			fmt.Printf("%s: Update failed - %s\n", productName, err.Error())
			failedUpdates++
			failedProducts = append(failedProducts, productName)
		} else {
			newQuantity := inventory[productName].Quantity
			if change > 0 {
				fmt.Printf("%s: Added %d units - New stock: %d\n", productName, change, newQuantity)
			} else if change < 0 {
				fmt.Printf("%s: Removed %d units - New stock: %d\n", productName, -change, newQuantity)
			} else {
				fmt.Printf("%s: No change - Current stock: %d\n", productName, newQuantity)
			}
			successfulUpdates++
		}
	}
	
	// Update summary
	fmt.Println("Update Summary:")
	fmt.Printf("Updates processed: %d\n", totalUpdates)
	fmt.Printf("Updates successful: %d\n", successfulUpdates)
	fmt.Printf("Updates failed: %d\n", failedUpdates)
	
	// Display updated inventory in alphabetical order
	fmt.Println("Updated Inventory:")
	var productNames []string
	for name := range inventory {
		productNames = append(productNames, name)
	}
	sort.Strings(productNames)
	
	for _, name := range productNames {
		product := inventory[name]
		fmt.Printf("- %s: $%.2f (Stock: %d)\n", name, product.Price, product.Quantity)
	}
	
	// Calculate final statistics
	totalProducts := len(inventory)
	totalItems := 0
	totalValue := 0.0
	
	for _, product := range inventory {
		totalItems += product.Quantity
		totalValue += product.Price * float64(product.Quantity)
	}
	
	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 failed updates
	if len(failedProducts) > 0 {
		fmt.Printf("Failed updates: %s\n", strings.Join(failedProducts, ","))
	} else {
		fmt.Println("All stock updates were processed successfully")
	}
}

All lessons in Logic & Flow