Poniéndolo todo junto
Parte de la sección Lógica y Flujo del Journey de GO de Coddy. Lección 50 de 68.
Desafío
FácilCompleta tu sistema de gestión de inventario creando un programa principal integral que reúna todas las funcionalidades que has desarrollado en lecciones anteriores. Este desafío final combina la inicialización del inventario, la comprobación de existencias, la incorporació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 mediante menús.
Recibirás tres entradas:
- Una cadena que contiene los datos iniciales del inventario con 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 del menú con 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 las operaciones con el formato
"param1|param2|param3", donde cada parámetro corresponde a la operación que ocupa la misma posición (por ejemplo,"Mouse|Monitor:299.99:10|Laptop:5|full,10")
Tu tarea es:
- Usar la misma estructura
Productde las lecciones anteriores, con los camposPrice(float64) yQuantity(int) - Analizar la primera entrada e inicializar el mapa del inventario con los datos de los productos existentes
- Mostrar el mensaje de inicio del sistema:
"=== INVENTORY MANAGEMENT SYSTEM ===""System initialized with [number_of_products] products""Starting interactive session..."
- Analizar la segunda entrada para obtener la secuencia de operaciones que se deben realizar
- Analizar la tercera entrada para obtener los parámetros de cada operación
- Para cada operación de la 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 presentar la información de salida
- Para
- Implementar la función
checkStock, que devuelve la cantidad y un error, como en las lecciones anteriores - Implementar la función
addNewItem, que añade productos y devuelve un error, como en las lecciones anteriores - Implementar la función
updateStock, que actualiza las cantidades y devuelve un error, como en las lecciones anteriores - Implementar la función
generateReport, que imprime el informe descrito más abajo para la operación"report" - Para la operación
"check":- Usar el parámetro como nombre del producto que se desea comprobar
- Mostrar:
"Checking stock for: [product_name]" - Si se encuentra:
"Stock level: [quantity] units" - Si no se encuentra:
"Product not found in inventory"
- Para la operación
"add":- Analizar el parámetro con el formato
"product_name:price:quantity" - Mostrar:
"Adding new product: [product_name]" - Si se completa correctamente:
"Product added successfully" - Si falla:
"Failed to add product: [error_message]", donde el error es"product already exists"
- Analizar el parámetro con el formato
- Para la operación
"update":- Analizar el parámetro con el formato
"product_name:change" - Mostrar:
"Updating stock for: [product_name]" - Si se completa correctamente y el cambio es cero o positivo:
"Added [change] units. New stock: [new_quantity]" - Si se completa correctamente y el cambio es negativo:
"Removed [absolute_change] units. New stock: [new_quantity]" - Si falla:
"Update failed: [error_message]", donde el error es"product not found"o"insufficient stock"cuando la nueva cantidad sería inferior a 0
- Analizar el parámetro con el formato
- Para la operación
"report":- Analizar el parámetro con el formato
"report_type,threshold", donde report_type es"low"o"full"y threshold es un número entero - Mostrar:
"Generating [report_type] report with threshold [threshold]" - Después, imprimir el informe con los productos en orden alfabético:
- Para
"low":"=== LOW REPORT ===", después"Products with stock below [threshold]:"y, luego,"- [name]: [quantity] units (Price: $[price])"para cada producto cuya cantidad sea inferior al umbral - Para
"full":"=== FULL REPORT ===", después"Complete inventory (minimum threshold: [threshold]):"y, luego,"- [name]: [quantity] units @ $[price] each [OK]"para cada producto, usando[LOW STOCK]en lugar de[OK]cuando la cantidad sea inferior al umbral
- Para
- Analizar el parámetro con el formato
- 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"
- Mostrar las estadísticas finales del inventario:
- 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 en números, el paquete errors para gestionar errores, el paquete fmt para dar formato a la salida y el paquete sort para ordenar alfabéticamente. Da formato a todos los precios y valores con 2 decimales. Este desafío demuestra cómo crear un sistema interactivo completo que integra varios componentes funcionales en una experiencia de usuario coherente, con una gestión adecuada de errores y del 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
1Flujo de control avanzado
Switch con `fallthrough`Salir de bucles anidadosContinuar un bucle específicoLa sentencia `goto`Repaso: Control de bucles avanzado4Proyecto: Lista de tareas sencilla
Configuración del proyectoAñadir una tarea2Estructuras y Métodos
Definición de métodos en estructurasReceptores de valorReceptores de punteroElegir receptoresMétodos vs FuncionesResumen - Comportamiento de estructuras5Mapas en profundidad
Mapas de StructsPunteros como valores de MapVerificación de Maps NilComparación de MapsResumen - Contador de frecuencia de palabras8Proyecto: Inventario simple
Descripción general del proyectoVerificar el stock3Interfaces (Conceptos básicos)
¿Qué es una interfaz?Definir una interfazImplementar una interfazUso de tipos de interfazInterfaz vacíaAserciones de tipoType SwitchResumen: Formas y comportamientosPractica por tu cuenta: Compilador de Go online