Funkcja składania zamówień z wyprzedzeniem (wersja 1)

W ramach realizacji zamówienia możesz zapewnić użytkownikom pomoc w planowaniu z wyprzedzeniem zamówień jedzenia z odbiorem i dostawą. Zanim wdrożysz tę obsługę, utwórz plik danych o asortymencie usługi zawierający godziny, w których użytkownicy mogą składać zamówienia w zamówieniu zgodnie ze schematem pliku danych o asortymencie (AdvanceServiceDeliveryHoursSpecification).

Przedziały zamówień z wyprzedzeniem

Google oferuje terminy składania zamówień z wyprzedzeniem w odstępach 15-minutowych, z maksymalnie 7-dniowym wyprzedzeniem, na podstawie czasu realizacji zamówienia w przypadku restauracji lub usługi (zgodnie z definicją w AdvanceServiceDeliveryHoursSpecification).

Aby pobrać proponowane przedziały zamówienia z wyprzedzeniem, użyj tych wartości w polu fulfillmentPreference obiektu FoodCartExtension w momencie płatności:

  • PickupInfo.pickupTimeIso8601
  • DeliveryInfo.deliveryTimeIso8601

Wdrażanie zamówień z góry w momencie płatności

W tabeli poniżej znajdziesz możliwe sposoby wdrożenia odpowiedzi na żądanie realizacji w momencie płatności, gdy użytkownicy próbują złożyć zamówienie.

Scenariusz Sposób realizacji
W przypadku żądanego przedziału czasu można zrealizować zamówienie z wyprzedzeniem. Zaakceptuj koszyk P0M („jak najszybciej”) lub FUTURE_SLOT, tworząc ProposedOrder z tym samym przedziałem. Przykład odpowiedzi płatności akceptującej przedział czasu znajdziesz w tym fragmentie kodu.
W przypadku żądanego przedziału czasu nie można zrealizować zamówienia z wyprzedzeniem. Realizacja zamówienia powinna wyglądać tak:
  1. Odrzuć żądany koszyk P0M lub FUTURE_SLOT i podaj powód, dla którego nie można zrealizować zamówienia w obiekcie FoodErrorExtension.
    • Jeśli zamówienia nie można zrealizować ze względu na pojemność, podaj FoodOrderError typu błędu NO_CAPACITY.
    • Jeśli nie można zrealizować zamówienia, ponieważ restauracja jest zamknięta, podaj FoodOrderError typu błędu CLOSED.
    • Jeśli zamówienia nie można zrealizować z innego powodu, podaj FoodOrderError typu błędu UNAVAILABLE_SLOT.
  2. Jeśli to możliwe, podaj alternatywne wartości P0M lub FUTURE_SLOT w correctedProposedOrder. Te wartości powinny być wszystkimi prawidłowymi przedziałami czasu realizacji na następne 7 dni, licząc od danego momentu. W razie potrzeby dodaj przedział P0M.

Przykład odpowiedzi dotyczącej płatności z propozycją alternatywnych przedziałów znajdziesz w tym fragmentie kodu.

Alternatywne przedziały do realizacji zamówień

Jeśli w momencie płatności proponowane przez Google terminy składania zamówień z wyprzedzeniem nie są odpowiednie, realizacja może zasugerować alternatywne rozwiązanie za pomocą obiektu CheckoutResponseMessage.

Aby określić alternatywne przedziały dla zamówień z wyprzedzeniem, odpowiedz na żądanie płatności za pomocą atrybutu FoodErrorExtension i ustaw te wartości:

  1. W parametrze foodOrderErrors określ typ błędu (np. UNAVAILABLE_SLOT, NO_CAPACITY lub CLOSED).
  2. W parametrze correctedProposedOrder podaj alternatywne wartości P0M lub FUTURE_SLOT za pomocą availableFulfillmentOptions.

Alternatywne przedziały czasu powinny obejmować następne 7 dni od momentu złożenia zamówienia i zawierać wszystkie przedziały, w których można zrealizować wybrany przez użytkownika koszyk.

Załóżmy na przykład, że oferty specjalne lunchowe są dostępne tylko od poniedziałku do piątku w godzinach 11:00–13:00. Użytkownik próbuje dodać do koszyka dania specjalne, ale wybrane przez niego miejsce jest niedostępne. W tym przypadku realizacja zamówienia powinna zawierać specjalne danie w koszyku i zwracać przez kolejne 7 dni tylko przedziały czasu między 11:00 a 13:00.

W odpowiedzi pomiń obiekt correctedProposedOrder.Cart.fulfillmentPreference.

Jeśli nie mamy wolnych terminów albo restauracja lub usługa nie obsługuje zamówień z wyprzedzeniem, nie musisz podawać właściwości correctedProposedOrder.

Poniżej znajdziesz przykłady komunikatów JSON między Twoją realizacją zamówień a Google w trakcie procesu płatności i odpowiedzi na zamówienie z wyprzedzeniem, gdy restauracja lub usługa są dostępne do składania zamówień w przedsprzedaży.

Przykład: żądanie płatności z przedziałem dostawy

Fragment kodu poniżej przedstawia przykład żądania płatności z przedziałem czasu dostawy zamówienia z wyprzedzeniem.

{
  "inputs": [
    {
      "intent": "actions.foodordering.intent.CHECKOUT",
      "arguments": [
        {
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.orders.Cart",
            "merchant": {
              "id": "https://www.exampleprovider.com/merchant/id1",
              "name": "Cucina Venti"
            },
            "lineItems": [
              {
                "name": "Sizzling Prawns Dinner",
                "type": "REGULAR",
                "id": "sample_item_offer_id_1",
                "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                "quantity": 1,
                "price": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
              }
            ],
            "extension": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
              "fulfillmentPreference": {
                "fulfillmentInfo": {
                  "delivery": {
                    // Deliver at 6:30PM.
                    "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                  }
                }
              },
              "location": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

Przykład: CheckoutResponse akceptuje przedział

Fragment kodu poniżej pokazuje przykładową odpowiedź na płatność, w której realizacja akceptuje proponowane przedziały dotyczące zamówień z wyprzedzeniem.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "checkoutResponse": {
              "proposedOrder": {
                "id": "sample_proposed_order_id_1",
                "cart": {
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Falafel Bite"
                  },
                  "lineItems": [
                    {
                      "name": "Sizzling Prawns Dinner",
                      "type": "REGULAR",
                      "id": "sample_item_offer_id_1",
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "16",
                          "nanos": 750000000
                        }
                      },
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "delivery": {
                          // Same as the time in the request.
                          "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                        }
                      }
                    },
                    "location": {
                      ...
                     }
                   }
                },
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    // Represents $16.75
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                  // Send whole proposed order back.
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        // Same as the time in the request.
                        "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                      }
                    }
                  ]
                }
              },
              "paymentOptions": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

Przykład: odpowiedź na żądanie płatności z dodatkowymi przedziałami

Fragment kodu poniżej pokazuje przykładową odpowiedź na płatność, w której realizacja proponuje alternatywne przedziały czasu w przypadku zamówień z wyprzedzeniem. Pamiętaj, że w odpowiedzi należy pominąć obiekt correctedProposedOrder.Cart.fulfillmentPreference.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "error": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
              "foodOrderErrors": [
                {
                  "error": "UNAVAILABLE_SLOT", // Cart level error
                  "description": "The restaurant is closed."
                }
              ],
              "correctedProposedOrder": {
                // Send whole original cart back,
                // without the fulfillmentPreference.
                "cart": {
                  ...
                },
                "otherItems": {
                  ...
                },
                "totalPrice": {
                  ...
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T19:00:00-07:00"
                      }
                    },
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T19:30:00-07:00"
                      }
                    },
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T20:00:00-07:00"
                      }
                    }
                  ]
                }
              },
              "paymentOptions": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

Wdrażanie zamówień z wyprzedzeniem podczas składania zamówienia

Jeśli przy przesyłaniu zamówienia wystąpi problem z przedziałami dla zamówień z wyprzedzeniem, SubmitOrderResponseMessage powinien podać przyczynę (np. UNAVAILABLE_SLOT lub UNKNOWN) w obiekcie RejectionInfo.

Po zaakceptowaniu zamówienia przez dostawcę zaktualizuj stan zamówienia z CREATED na CONFIRMED w obiekcie OrderState. Podaj wybrany przedział czasu w e-mailu z potwierdzeniem wysłanym do użytkownika.

Jeśli po złożeniu zamówienia zamówienie zostanie wysłane do restauracji później, wyślij do Google aktualizację, korzystając z asynchronicznego działania aktualizacji zamówienia.

W obiekcie OrderUpdate w odpowiedzi na przesłanie zamówienia lub kolejnych asynchronicznych aktualizacjach zamówień umieść tag estimatedFulfillmentTimeIso8601 z tą wartością:

  • Gdy stan zamówienia to CREATED lub CONFIRMED, jako wartość ustaw czas dostawy lub odbioru, który użytkownik zaplanował w związku z zamówieniem z wyprzedzeniem.
  • Jeśli istnieje dokładniejszy przewidywany czas dostawy do restauracji lub usługi, ustaw wartość na szacowany czas dostawy lub odbioru.

Przykład: SubmitOrderRequest z boksem dostawy

Fragment kodu poniżej pokazuje przykład prośby o przesłanie zamówienia, która wskazuje przedział wcześniejszego zamówienia wybrany przez użytkownika.

{
  "inputs": [
    {
      "intent": "actions.intent.TRANSACTION_DECISION",
      "arguments": [
        {
          "transactionDecisionValue": {
            "order": {
              "finalOrder": {
                "cart": {
                  "notes": "Guest prefers their food to be hot when it is delivered.",
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Cucina Venti"
                  },
                  "lineItems": [
                    {
                      "name": "Sizzling Prawns Dinner",
                      "type": "REGULAR",
                      "id": "sample_item_offer_id_1",
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "16",
                          "nanos": 750000000
                        }
                      }
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "delivery": {
                          "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                        }
                      }
                    }
                    "contact": {
                      ...
                    }
                  }
                },
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "16",
                    "nanos": 750000000
                  }
                },
                "id": "sample_final_order_id",
                "extension": {
                  // Send whole proposed order back.
                  "availableFulfillmentOptions": [
                    "fulfillmentInfo": {
                      "delivery": {
                        "deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
                      }
                   ]
                }
              },
              "googleOrderId": "sample_google_order_id",
              "orderDate": "2017-07-17T12:00:00Z",
              "paymentInfo": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

Przykład: przesłana odpowiedź na zamówienie akceptacja zamówienia

Fragment kodu poniżej pokazuje przykładową odpowiedź na zamówienie, w której Twoja realizacja potwierdza, że przyjęła ona zamówienie z wyprzedzeniem użytkownika.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "sample_action_order_id",
              "orderState": {
                "state": "CREATED",
                "label": "Order placed"
              },
              "receipt": {
                "userVisibleOrderId": "userVisibleId1234"
              },
              "updateTime": "2017-07-17T12:00:00Z",
              "orderManagementActions": [
                ...
              ],
              "infoExtension": {
                 "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
                 // Same as the user selected time.
                 "estimatedFulfillmentTimeIso8601": "2017-12-14T18:30:00-07:00"
              }
            }
          }
        }
      ]
    }
  }
}

Przykład: odrzucenie zamówienia z powodu niedostępności przedziału czasu

Fragment kodu poniżej pokazuje przykładową odpowiedź na zamówienie, w której realizacja odrzuca z wyprzedzeniem zamówienie użytkownika z powodu niedostępnego przedziału.

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "sample_action_order_id",
              "orderState": {
                "state": "REJECTED",
                "label": "Unavailable slot"
              },
              "rejectionInfo": {
                // Note that this UNAVAILABLE_SLOT is different from the enum
                // with the same name proposed for FoodOrderError.
                "state": "UNAVAILABLE_SLOT",
                "label": "Unavailable slot"
              },
              "updateTime": "2017-07-17T12:00:00Z",
              "orderManagementActions": [
                ...
              ]
            }
          }
        }
      ]
    }
  }
}

Przykłady zamówień zaawansowanych

Typu AdvanceServiceDeliveryHoursSpecification możesz użyć do określenia godzin dostawy lub odbioru, w przypadku których użytkownicy będą mogli zaplanować zamówienie z wyprzedzeniem.

Uwaga: w przypadku realizacji usługi musisz podać 2 oddzielne przedziały czasowe: okres składania zamówień, który określa, kiedy użytkownicy mogą złożyć zamówienie, i okres realizacji, który określa, kiedy zamówienie zostanie zrealizowane. Obiekt OpeningHoursSpecification określa, kiedy użytkownik może złożyć zamówienie. Czas realizacji zamówienia podrzędnego (ServiceDeliveryHoursSpecification lub AdvanceServiceDeliveryHoursSpecification) określa, kiedy można zrealizować zamówienie.

Poniższy przykład określa godziny pracy usługi w przypadku akceptowania zamówień z wyprzedzeniem przy 15-minutowych odstępach czasu.

{
  "hoursAvailable": [
    {
      "@type": "OpeningHoursSpecification",
      "opens": "T00:00:00", // Ordering available 24 hours
      "closes": "T23:59:59",
      "deliveryHours": [
        {
          "@type": "ServiceDeliveryHoursSpecification",
          "opens": "T09:00:00", // ASAP orders b/w 9am and 8:59:59pm
          "closes": "T21:00:00",
          "deliveryLeadTime": {
            "value": "60",
            "unitCode": "MIN"
          }
        },
        {
          "@type": "AdvanceServiceDeliveryHoursSpecification",
          "opens": "T10:00:00",  // Delivery between 10AM and 7:59:59PM
          "closes": "T20:00:00",
          "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart (ISO8601)
          "advanceBookingRequirement": {
            "minValue": 60,   // The slot should be at least 60 mins away
            "maxValue": 8640, // but not more than 6 days away
            "unitCode": "MIN"
          }
        }
      ]
    }
  ]
}

Poniższy przykład pokazuje, jak możesz określić, że usługa jest dostępna w przypadku zamówień tego samego dnia w Boże Narodzenie, ale zamknięta w przypadku zamówień zaawansowanych zaplanowanych na ten dzień. Ten przykład obsługuje następujące scenariusze:

  • Użytkownicy mogą złożyć zamówienie 25 grudnia, aby otrzymać przesyłkę tego samego dnia.
  • Użytkownicy mogą złożyć zamówienie z wyprzedzeniem 25 grudnia, a dostawa zaplanowana na 27 grudnia.
  • Użytkownicy nie mogą składać zamówień z wyprzedzeniem 22 grudnia w przypadku dostawy zaplanowanej na 25 grudnia.
{
  "specialOpeningHoursSpecification": {
    "@type": "AdvanceServiceDeliveryHoursSpecification",
    "validFrom": "2018-12-25T00:00:00-07:00",
    "validThrough": "2018-12-26T00:00:00-07:00",
    "opens": "T00:00:00", // No advance ordering
    "closes": "T00:00:00"
  }
}

Poniższy przykład pokazuje, jak możesz określić, że usługa jest zamknięta w przypadku zamówień składanych tego samego dnia lub zamówień z wyprzedzeniem zaplanowanych na Boże Narodzenie, ale jest otwarta w przypadku zamówień zaawansowanych zaplanowanych na późniejszy dzień. W tym przykładzie opisano te scenariusze:

  • Użytkownicy nie mogą złożyć zamówienia 25 grudnia na dostawę tego samego dnia.
  • Użytkownicy mogą złożyć zamówienie z wyprzedzeniem 25 grudnia, a dostawa zaplanowana na 27 grudnia.
  • Użytkownicy nie mogą składać zamówień z wyprzedzeniem 22 grudnia w przypadku dostawy zaplanowanej na 25 grudnia.
{
  "specialOpeningHoursSpecification": [
    {
      "@type": "ServiceDeliveryHoursSpecification",
      "validFrom": "2018-12-25T00:00:00-07:00",
      "validThrough": "2018-12-26T00:00:00-07:00",
      "opens": "T00:00:00", // No ASAP ordering on Christmas
      "closes": "T00:00:00"
    },
    {
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "validFrom": "2018-12-25T00:00:00-07:00",
      "validThrough": "2018-12-26T00:00:00-07:00",
      "opens": "T00:00:00", // Orders cannot be scheduled for Christmas
      "closes": "T00:00:00"
    }
  ]
}

Poniższa przykładowa usługa akceptuje zamówienia przez całą dobę, 7 dni w tygodniu od 10:00 do 14:59:59 w dni robocze:

...
{
  "@type": "OpeningHoursSpecification",
  "opens": "T00:00:00",
  "closes": "T23:59:59",
  "deliveryHours": {
    "@type": "AdvanceServiceDeliveryHoursSpecification",
    "opens": "T10:00:00", // Delivery starts at 10:00AM
    "closes": "T15:00:00", // Delivery ends at 3:00PM. Delivery from 10AM-2:59:59PM.
    "dayOfWeek": [
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday"
    ],
    "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart
    "advanceBookingRequirement": {
      "minValue": 60,   // The slot should be at least 60 mins away
      "maxValue": 8640, // but not more than 6 days away
      "unitCode": "MIN"
    }
  }
}
...

Poniższa przykładowa usługa przyjmuje zamówienia codziennie od 8:00 do 16:59:59. Klienci mogą zdecydować się na dostawę w ciągu godziny lub wybrać jeden z przedziałów:

...
{
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",  // Ordering opens at 8:00AM
  "closes": "T17:00:00",  // Ordering closes at 5:00PM, last order at 4:59:59PM
  "deliveryHours": [
    {
      "@type": "ServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "deliveryLeadTime": {
        "@type": "QuantitativeValue",
        "value": "60", // If no exact deliveryLeadTime, put a maximum time
        "unitCode": "MIN"
      }
    },
    {
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart
      "advanceBookingRequirement": {
        "minValue": 90,   // The slot should be at least 90 mins away
        "maxValue": 8640, // but not more than 6 days away
        "unitCode": "MIN"
      }
    }
  ]
}
...

Poniższy przykład przedstawia przypadek, w którym sklep jest otwarty od 8:00 do 16:59:59 w dni powszednie, ale od 8:00 do 18:59 w weekendy. Zamówienia nie są przyjmowane przez całą dobę, 7 dni w tygodniu.

...
{
  // On weekdays, ordering open from 8AM-4:59:59PM.
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",
  "closes": "T17:00:00",
  "dayOfWeek": [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday"
  ],
  "deliveryHours": [
    {
      // Fulfillment between 8AM-4:59:59PM on weekdays.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "dayOfWeek": [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    },
    {
      // Fulfillment between 8AM-6:59:59PM on weekends (even for orders placed on a
      // weekday).
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T19:00:00",
      "dayOfWeek": [
        "Saturday",
        "Sunday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    }
  ]
},
{
  // On weekends, one can place orders upto 6:59:59PM.
  "@type": "OpeningHoursSpecification",
  "opens": "T08:00:00",
  "closes": "T19:00:00",
  "dayOfWeek": [
    "Saturday",
    "Sunday"
  ],
  "deliveryHours": [
    {
      // But fulfillment on weekdays is only till 4:59:59PM.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T17:00:00",
      "dayOfWeek": [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    },
    {
      // Fulfillment on weekends is till 6:59:59PM.
      "@type": "AdvanceServiceDeliveryHoursSpecification",
      "opens": "T08:00:00",
      "closes": "T19:00:00",
      "dayOfWeek": [
        "Saturday",
        "Sunday"
      ],
      "serviceTimeInterval": "PT15M",
      "advanceBookingRequirement": {
        "minValue": 60,
        "maxValue": 8640,
        "unitCode": "MIN"
      }
    }
  ]
}
...