Sobes.tech
Middle+

grpc-sunucu yöntemi AddItemAndOrder'ı uygulayın: 1. Ürünleri sepete ekleyin 2. Sepetin oluşturulmasıyla ilgili bilgiyi mesaj broker aracılığıyla potansiyel tüketicilere bildirmek zorunludur. 3. Sepetin içeriği değiştiğinde, basket.Total=sum(adet*fiyat) olarak yeniden hesaplanmalıdır 4. Sepetteki tüm öğeler ProductID anahtarına göre benzersiz olmalıdır 5. Sepet sipariş edilmek üzere durumunu ordered olarak değiştirmek gerekir 6. Sipariş edilen sepetlerde değişiklik yapılamaz

sobes.tech yapay zeka

AI'dan gelen yanıt

Ниже пример реализации метода AddItemAndOrder для gRPC-сервера на Go с учетом требований:

  • Корзина (Basket) содержит уникальные товары по ProductID.
  • При добавлении товаров пересчитывается сумма Total.
  • При оформлении корзины меняется статус на ordered.
  • После оформления изменения запрещены.
  • После оформления отправляется сообщение через брокер (например, через интерфейс MessageBroker).
package service

import (
    "context"
    "errors"
    "sync"
)

// Пример структур

type BasketStatus string

const (
    StatusOpen    BasketStatus = "open"
    StatusOrdered BasketStatus = "ordered"
)

type BasketItem struct {
    ProductID string
    Count     int
    Price     float64
}

type Basket struct {
    ID     string
    Items  map[string]*BasketItem // ключ - ProductID
    Total  float64
    Status BasketStatus
    mu     sync.Mutex
}

// Интерфейс брокера сообщений

type MessageBroker interface {
    Publish(topic string, message interface{}) error
}

// Сервис с корзинами и брокером

type BasketService struct {
    baskets map[string]*Basket
    broker  MessageBroker
}

func NewBasketService(broker MessageBroker) *BasketService {
    return &BasketService{
        baskets: make(map[string]*Basket),
        broker:  broker,
    }
}

// AddItemAndOrderRequest и Response - protobuf-сгенерированные структуры

func (s *BasketService) AddItemAndOrder(ctx context.Context, req *AddItemAndOrderRequest) (*AddItemAndOrderResponse, error) {
    basket, ok := s.baskets[req.BasketId]
    if !ok {
        return nil, errors.New("basket not found")
    }

    basket.mu.Lock()
    defer basket.mu.Unlock()

    if basket.Status == StatusOrdered {
        return nil, errors.New("cannot modify ordered basket")
    }

    // Добавляем или обновляем товары
    for _, item := range req.Items {
        if existing, exists := basket.Items[item.ProductId]; exists {
            existing.Count += int(item.Count)
            existing.Price = item.Price // обновляем цену, если нужно
        } else {
            basket.Items[item.ProductId] = &BasketItem{
                ProductID: item.ProductId,
                Count:     int(item.Count),
                Price:     item.Price,
            }
        }
    }

    // Пересчет суммы
    var total float64
    for _, item := range basket.Items {
        total += float64(item.Count) * item.Price
    }
    basket.Total = total

    // Если в запросе есть флаг оформления корзины
    if req.Order { // предположим, что есть булево поле Order
        basket.Status = StatusOrdered

        // Отправляем сообщение в брокер
        err := s.broker.Publish("basket_ordered", map[string]interface{}{
            "basket_id": basket.ID,
            "total":     basket.Total,
            "items":     basket.Items,
        })
        if err != nil {
            return nil, err
        }
    }

    return &AddItemAndOrderResponse{
        Total:  basket.Total,
        Status: string(basket.Status),
    }, nil
}

В этом примере:

  • Используется мьютекс для защиты данных корзины от гонок.
  • Товары хранятся в мапе для уникальности по ProductID.
  • При оформлении меняется статус и отправляется событие через брокер.
  • После оформления любые изменения запрещены.

Для реального приложения нужно добавить валидацию, обработку ошибок и интеграцию с реальным брокером сообщений.