Menu
Coddy logo textTech

Обновление количества товара

Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 48 из 68.

challenge icon

Задание

Легко

Улучшите свою систему управления запасами, реализовав обновление количества товаров на складе с комплексной валидацией и обработкой ошибок. Эта задача опирается на предыдущую функциональность и добавляет возможность изменять количество существующих продуктов, предотвращая при этом недопустимые операции, которые могут привести к отрицательному уровню запасов.

Вы получите два входных значения:

  • Строка, содержащая данные о текущем инвентаре в формате "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3" (например, "Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8")
  • Строка, содержащая запросы на обновление запасов в формате "product1:change1,product2:change2,product3:change3", где изменения могут быть положительными или отрицательными целыми числами (например, "Mouse:10,Tablet:-5,Keyboard:-3")

Ваша задача:

  1. Использовать ту же структуру Product из предыдущих уроков с полями Price (float64) и Quantity (int)
  2. Разобрать первый входной параметр, разделив его по запятым, чтобы получить записи об отдельных существующих продуктах
  3. Для каждой записи о продукте разделить её по двоеточиям, чтобы получить название продукта, цену и количество
  4. Преобразовать строку цены в float64, а строку количества в int
  5. Создать и заполнить карту (map) inventory данными о существующих продуктах
  6. Создать функцию с именем updateStock, которая принимает карту inventory, название продукта и изменение количества в качестве параметров и возвращает ошибку:
    • Если продукт не существует в инвентаре, вернуть ошибку с сообщением "product not found: [product_name]"
    • Если изменение количества приведет к отрицательному остатку (текущее количество + изменение < 0), вернуть ошибку с сообщением "insufficient stock: cannot reduce [product_name] by [absolute_change_value], only [current_quantity] available"
    • Если обновление допустимо, изменить количество продукта в инвентаре и вернуть nil
  7. Разобрать второй входной параметр, разделив его по запятым, чтобы получить список запросов на обновление запасов
  8. Для каждого запроса на обновление разделить его по двоеточиям, чтобы получить название продукта и изменение количества
  9. Преобразовать строку изменения количества в int
  10. Вывести заголовок процесса обновления: "Processing Stock Updates:"
  11. Для каждого запроса на обновление вызвать функцию updateStock и вывести результаты:
    • Если ошибки нет и изменение положительное: "[product_name]: Added [change] units - New stock: [new_quantity]"
    • Если ошибки нет и изменение отрицательное: "[product_name]: Removed [absolute_change_value] units - New stock: [new_quantity]"
    • Если ошибки нет и изменение равно нулю: "[product_name]: No change - Current stock: [current_quantity]"
    • Если возникла ошибка: "[product_name]: Update failed - [error_message]"
  12. Подсчитать и вывести статистику обновлений:
    • "Update Summary:"
    • "Updates processed: [total_number_of_updates_processed]"
    • "Updates successful: [number_of_successful_updates]"
    • "Updates failed: [number_of_failed_updates]"
  13. Вывести обновленный инвентарь в алфавитном порядке по названию продукта:
    • "Updated Inventory:"
    • Для каждого продукта: "- [product_name]: $[price] (Stock: [quantity])"
  14. Рассчитать и вывести итоговую статистику инвентаря:
    • "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. Перечислить все неудачные обновления:
    • Если есть неудачные обновления: "Failed updates: [comma_separated_list_of_failed_product_names]"
    • Если неудачных обновлений нет: "All stock updates were processed successfully"

Используйте пакет strings для разделения входных строк, пакет strconv для преобразования строк в числа, пакет errors для создания сообщений об ошибках, пакет fmt для форматированного вывода и пакет sort для сортировки названий продуктов по алфавиту. Форматируйте все цены до 2 знаков после запятой и общую стоимость инвентаря также до 2 знаков после запятой. Эта задача демонстрирует, как безопасно изменять существующие данные, предотвращая недопустимые операции с помощью комплексной валидации и обработки ошибок.

Попробуйте сами

package main

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

type Product struct {
	Price    float64
	Quantity int
}

func addNewItem(inventory map[string]Product, productName string, price float64, quantity int) error {
	if _, exists := inventory[productName]; exists {
		return errors.New("product already exists: " + productName)
	}
	inventory[productName] = Product{Price: price, Quantity: quantity}
	return nil
}

func main() {
	var existingInventory string
	var newProducts string
	fmt.Scanln(&existingInventory)
	fmt.Scanln(&newProducts)

	inventory := make(map[string]Product)

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

	// Parse new products to add
	newItems := strings.Split(newProducts, ",")
	
	fmt.Println("Adding New Items:")
	
	itemsProcessed := 0
	itemsAdded := 0
	itemsRejected := 0
	var rejectedProducts []string

	for _, item := range newItems {
		parts := strings.Split(item, ":")
		name := parts[0]
		price, _ := strconv.ParseFloat(parts[1], 64)
		quantity, _ := strconv.Atoi(parts[2])
		
		itemsProcessed++
		
		err := addNewItem(inventory, name, price, quantity)
		if err != nil {
			fmt.Printf("%s: Failed to add - %s\n", name, err.Error())
			itemsRejected++
			rejectedProducts = append(rejectedProducts, name)
		} else {
			fmt.Printf("%s: Successfully added - $%.2f (Stock: %d)\n", name, price, quantity)
			itemsAdded++
		}
	}

	// Addition summary
	fmt.Println("Addition Summary:")
	fmt.Printf("Items processed: %d\n", itemsProcessed)
	fmt.Printf("Items added: %d\n", itemsAdded)
	fmt.Printf("Items rejected: %d\n", itemsRejected)

	// Display updated inventory in alphabetical order
	fmt.Println("Updated Inventory:")
	var productNames []string
	for name := range inventory {
		productNames = append(productNames, name)
	}
	sort.Strings(productNames)

	totalProducts := 0
	totalItems := 0
	totalValue := 0.0

	for _, name := range productNames {
		product := inventory[name]
		fmt.Printf("- %s: $%.2f (Stock: %d)\n", name, product.Price, product.Quantity)
		totalProducts++
		totalItems += product.Quantity
		totalValue += product.Price * float64(product.Quantity)
	}

	// Final inventory statistics
	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 rejected products
	if len(rejectedProducts) > 0 {
		fmt.Printf("Rejected products: %s\n", strings.Join(rejectedProducts, ","))
	} else {
		fmt.Println("All new products were added successfully")
	}
}

Все уроки раздела Логика и управление потоком