تحديث كمية المخزون
جزء من قسم Logic & Flow في رحلة 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
- إنشاء وتعبئة خريطة
inventoryببيانات المنتجات الحالية - إنشاء دالة تسمى
updateStockتأخذ خريطة المخزون، واسم المنتج، وتغيير الكمية كمعاملات (parameters) وتعيد خطأ (error):- إذا لم يكن المنتج موجوداً في المخزون، فقم بإرجاع خطأ بالرسالة
"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 لفرز أسماء المنتجات أبجدياً. قم بتنسيق جميع الأسعار إلى منزلتين عشريتين وقيمة المخزون الإجمالية إلى منزلتين عشريتين. يوضح هذا التحدي كيفية تعديل البيانات الموجودة بأمان مع منع العمليات غير الصالحة من خلال التحقق الشامل ومعالجة الأخطاء.
جرّب بنفسك
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")
}
}جميع دروس Logic & Flow
1تدفق التحكم المتقدم
جملة Switch مع `fallthrough`الخروج من الحلقات المتداخلةالاستمرار في حلقة محددةجملة `goto`ملخص - التحكم المتقدم في الحلقات2الـ Structs والميثودز (Methods)
تعريف الـ Methods على الـ Structsالـ Value Receiversالـ Pointer Receiversاختيار الـ Receiversالـ Methods مقابل الـ Functionsملخص - سلوك الـ Struct5تعمق في الـ Maps
Maps من نوع Structsالـ Pointers كقيم في الـ Mapsالتحقق من الـ Nil Mapsمقارنة الـ Mapsمراجعة - عداد تكرار الكلمات8مشروع: مخزون بسيط
نظرة عامة على المشروعالتحقق من المخزون3الواجهات (الأساسيات)
ما هي الواجهة؟تعريف الواجهةتطبيق الواجهةاستخدام أنواع الواجهاتالواجهة الفارغةتأكيدات النوع (Type Assertions)تبديل النوع (Type Switch)ملخص - الأشكال والسلوكيات