Sobes.tech
Middle+

Implementacja metody grpc-serwera AddItemAndOrder: 1. Dodaj produkty do koszyka 2. Obowiązkowo poinformuj potencjalnych odbiorców o fakcie utworzenia koszyka przez brokera wiadomości. 3. Przy zmianie składu koszyka należy ponownie obliczyć basket.Total = suma(ilość * cena) 4. Wszystkie elementy koszyka muszą być unikalne według klucza ProductID 5. Aby złożyć zamówienie, należy zmienić jego status na ordered 6. Nie można wprowadzać zmian w już zamówionych koszykach Istnieje tabela, w której wszystkie kolumny są typu integer. W kodzie znajduje się zapytanie: select * from t1 where a > ? and b = ? and c != ? order by a;

sobes.tech AI

Odpowiedź od AI

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

func (s *Server) AddItemAndOrder(ctx context.Context, req *pb.AddItemAndOrderRequest) (*pb.AddItemAndOrderResponse, error) {
    basketID := req.GetBasketId()
    newItems := req.GetItems() // список товаров для добавления

    // Получаем корзину из БД
    basket, err := s.store.GetBasket(ctx, basketID)
    if err != nil {
        return nil, err
    }

    if basket.Status == "ordered" {
        return nil, status.Errorf(codes.FailedPrecondition, "Нельзя изменять оформленную корзину")
    }

    // Создаем карту для уникальности по ProductID
    itemsMap := make(map[int32]*pb.Item)
    for _, item := range basket.Items {
        itemsMap[item.ProductId] = item
    }

    // Добавляем/обновляем товары
    for _, newItem := range newItems {
        itemsMap[newItem.ProductId] = newItem
    }

    // Пересчитываем total
    var total int32 = 0
    var updatedItems []*pb.Item
    for _, item := range itemsMap {
        total += item.Count * item.Price
        updatedItems = append(updatedItems, item)
    }

    // Обновляем корзину
    basket.Items = updatedItems
    basket.Total = total

    // Если в запросе есть флаг оформления, меняем статус
    if req.GetOrder() {
        basket.Status = "ordered"
    }

    // Сохраняем изменения
    err = s.store.UpdateBasket(ctx, basket)
    if err != nil {
        return nil, err
    }

    // Если корзина оформлена, публикуем событие в брокер сообщений
    if basket.Status == "ordered" {
        err = s.messageBroker.Publish("basket_ordered", basket)
        if err != nil {
            return nil, err
        }
    }

    return &pb.AddItemAndOrderResponse{Basket: basket}, nil
}

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

  • Все товары уникальны по ProductID благодаря карте itemsMap.
  • При изменении состава корзины пересчитывается Total.
  • Статус меняется на ordered при оформлении.
  • Изменения в оформленную корзину запрещены.
  • После оформления публикуется событие в брокер сообщений.

По поводу SQL-запроса:

select * from t1 where a > ? and b = ? and c != ? order by a;

Это пример параметризованного запроса, где ? — плейсхолдеры для значений. Такой подход помогает избежать SQL-инъекций и улучшает читаемость кода.