Menu
Coddy logo textTech

Poniéndolo todo junto

Parte de la sección Lógica y Flujo del Journey de GO de Coddy — lección 50 de 68.

challenge icon

Desafío

Fácil

Completa tu sistema de gestión de inventario creando un programa principal integral que integre toda la funcionalidad que has construido en lecciones anteriores. Este desafío final reúne la inicialización del inventario, la comprobación de existencias, la adición de artículos, las actualizaciones de existencias y la generación de informes en una interfaz de línea de comandos completa con navegación basada en menús.

Recibirás tres entradas:

  • Una cadena que contiene los datos iniciales del inventario en el formato "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3" (por ejemplo, "Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8")
  • Una cadena que contiene una secuencia de operaciones de menú en el formato "operation1,operation2,operation3" donde las operaciones pueden ser "check", "add", "update", "report", o "exit" (por ejemplo, "check,add,update,report,exit")
  • Una cadena que contiene los parámetros de la operación en el formato "param1|param2|param3" donde cada parámetro corresponde a la operación en la misma posición (por ejemplo, "Mouse|Monitor:299.99:10|Laptop:5|full,10")

Tu tarea es:

  1. Usar el mismo struct Product de lecciones anteriores con los campos Price (float64) y Quantity (int)
  2. Analizar la primera entrada e inicializar el mapa de inventario con los datos de productos existentes
  3. Mostrar el mensaje de inicio del sistema:
    • "=== INVENTORY MANAGEMENT SYSTEM ==="
    • "System initialized with [number_of_products] products"
    • "Starting interactive session..."
  4. Analizar la segunda entrada para obtener la secuencia de operaciones a realizar
  5. Analizar la tercera entrada para obtener los parámetros de cada operación
  6. Para cada operación en secuencia, mostrar el encabezado de la operación y realizar la acción correspondiente:
    • Para "check": Mostrar "--- STOCK CHECK ---" y comprobar las existencias del producto especificado
    • Para "add": Mostrar "--- ADD ITEM ---" y añadir el producto especificado
    • Para "update": Mostrar "--- UPDATE STOCK ---" y actualizar las existencias del producto especificado
    • Para "report": Mostrar "--- GENERATE REPORT ---" y generar el informe especificado
    • Para "exit": Mostrar "--- SYSTEM EXIT ---" y mostrar la información de salida
  7. Implementar la función checkStock que devuelve la cantidad y un error como en lecciones anteriores
  8. Implementar la función addNewItem que añade productos y devuelve un error como en lecciones anteriores
  9. Implementar la función updateStock que actualiza las cantidades y devuelve un error como en lecciones anteriores
  10. Implementar la función generateReport que crea informes como en lecciones anteriores
  11. Para la operación "check":
    • Usar el parámetro como el nombre del producto a comprobar
    • Mostrar: "Checking stock for: [product_name]"
    • Si se encuentra: "Stock level: [quantity] units"
    • Si no se encuentra: "Product not found in inventory"
  12. Para la operación "add":
    • Analizar el parámetro en formato "product_name:price:quantity"
    • Mostrar: "Adding new product: [product_name]"
    • Si tiene éxito: "Product added successfully"
    • Si falla: "Failed to add product: [error_message]"
  13. Para la operación "update":
    • Analizar el parámetro en formato "product_name:change"
    • Mostrar: "Updating stock for: [product_name]"
    • Si tiene éxito y el cambio es positivo: "Added [change] units. New stock: [new_quantity]"
    • Si tiene éxito y el cambio es negativo: "Removed [absolute_change] units. New stock: [new_quantity]"
    • Si falla: "Update failed: [error_message]"
  14. Para la operación "report":
    • Analizar el parámetro en formato "report_type,threshold"
    • Mostrar: "Generating [report_type] report with threshold [threshold]"
    • Generar y mostrar el informe completo como en lecciones anteriores
  15. Para la operación "exit":
    • Mostrar las estadísticas finales del inventario:
      • "Final inventory status:"
      • "Total products: [total_products]"
      • "Total items: [total_items]"
      • "Total value: $[total_value]"
    • Mostrar: "Session completed successfully"
    • Mostrar: "Thank you for using the Inventory Management System"
  16. Después de cada operación (excepto exit), mostrar: "Operation completed. Continuing to next operation..."

Usa el paquete strings para dividir las cadenas de entrada, el paquete strconv para convertir cadenas a números, el paquete errors para el manejo de errores, el paquete fmt para la salida formateada y el paquete sort para el ordenamiento alfabético. Formatea todos los precios y valores a 2 decimales. Este desafío demuestra cómo crear un sistema interactivo completo que integra múltiples componentes funcionales en una experiencia de usuario cohesiva con un manejo adecuado de errores y gestión de estado.

Pruébalo tú mismo

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)
}

Todas las lecciones de Lógica y Flujo