Menu
Coddy logo textTech

재고 수량 업데이트하기

Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨 — 68개 중 48번째.

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. 이전 레슨과 동일하게 Price (float64) 및 Quantity (int) 필드를 가진 Product 구조체를 사용합니다.
  2. 첫 번째 입력을 쉼표로 분할하여 개별 기존 제품 항목을 가져와 파싱합니다.
  3. 각 기존 제품 항목에 대해 콜론으로 분할하여 제품 이름, 가격 및 수량을 가져옵니다.
  4. 가격 문자열을 float64로, 수량 문자열을 int로 변환합니다.
  5. 기존 제품 데이터로 inventory 맵을 생성하고 채웁니다.
  6. 재고 맵, 제품 이름, 수량 변경 값을 매개변수로 받고 에러를 반환하는 updateStock 함수를 만듭니다:
    • 제품이 재고에 존재하지 않으면, "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]"
    • 에러가 없고 변경 값이 0인 경우: "[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")
	}
}

로직 & 흐름의 모든 레슨