Обновление количества товара
Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 48 из 68.
Задание
ЛегкоУлучшите свою систему управления запасами, реализовав обновление количества товаров на складе с комплексной валидацией и обработкой ошибок. Эта задача опирается на предыдущую функциональность и добавляет возможность изменять количество существующих продуктов, предотвращая при этом недопустимые операции, которые могут привести к отрицательному уровню запасов.
Вы получите два входных значения:
- Строка, содержащая данные о текущем инвентаре в формате
"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")
Ваша задача:
- Использовать ту же структуру
Productиз предыдущих уроков с полямиPrice(float64) иQuantity(int) - Разобрать первый входной параметр, разделив его по запятым, чтобы получить записи об отдельных существующих продуктах
- Для каждой записи о продукте разделить её по двоеточиям, чтобы получить название продукта, цену и количество
- Преобразовать строку цены в float64, а строку количества в int
- Создать и заполнить карту (map)
inventoryданными о существующих продуктах - Создать функцию с именем
updateStock, которая принимает карту inventory, название продукта и изменение количества в качестве параметров и возвращает ошибку:- Если продукт не существует в инвентаре, вернуть ошибку с сообщением
"product not found: [product_name]" - Если изменение количества приведет к отрицательному остатку (текущее количество + изменение < 0), вернуть ошибку с сообщением
"insufficient stock: cannot reduce [product_name] by [absolute_change_value], only [current_quantity] available" - Если обновление допустимо, изменить количество продукта в инвентаре и вернуть nil
- Если продукт не существует в инвентаре, вернуть ошибку с сообщением
- Разобрать второй входной параметр, разделив его по запятым, чтобы получить список запросов на обновление запасов
- Для каждого запроса на обновление разделить его по двоеточиям, чтобы получить название продукта и изменение количества
- Преобразовать строку изменения количества в int
- Вывести заголовок процесса обновления:
"Processing Stock Updates:" - Для каждого запроса на обновление вызвать функцию
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]"
- Если ошибки нет и изменение положительное:
- Подсчитать и вывести статистику обновлений:
"Update Summary:""Updates processed: [total_number_of_updates_processed]""Updates successful: [number_of_successful_updates]""Updates failed: [number_of_failed_updates]"
- Вывести обновленный инвентарь в алфавитном порядке по названию продукта:
"Updated Inventory:"- Для каждого продукта:
"- [product_name]: $[price] (Stock: [quantity])"
- Рассчитать и вывести итоговую статистику инвентаря:
"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]"
- Перечислить все неудачные обновления:
- Если есть неудачные обновления:
"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")
}
}Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком выполнения
Switch с использованием `fallthrough`Выход из вложенных цикловПродолжение конкретного циклаОператор `goto`Итоги: Продвинутое управление циклами4Проект: Простой список задач
Настройка проектаДобавление задачи2Структуры и методы
Определение методов для структурПолучатели по значениюПолучатели по указателюВыбор типа получателяМетоды против функцийИтоги: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картИтоги: счетчик частоты слов8Проект: Простой учет товаров
Обзор проектаПроверка остатков3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведение