ميزة "الطلب المسبق" من الإصدار 1

يمكنك إضافة دعم في التنفيذ للمستخدمين لتحديد موعد استلام طلبات الطعام وتوصيلها مسبقًا. قبل تنفيذ عملية الدعم هذه، يجب إنشاء خلاصة مستودع الخدمة التي تحدّد الساعات المسموح بها للمستخدمين لتقديم طلبات مسبقة، كما هو موضّح في مخطط خلاصة المستودع (AdvanceServiceDeliveryHoursSpecification).

خانات الطلب المتقدمة

تقترح Google خانات الطلبات المسبقة بزيادات قدرها 15 دقيقة، لمدة تصل إلى 7 أيام مسبقة، بناءً على أوقات توصيل الطلبات في مطعم أو خدمة (على النحو المحدّد في AdvanceServiceDeliveryHoursSpecification).

لاسترداد الخانات المقترحة للطلب المسبق، استخدِم القيم التالية من الحقل fulfillmentPreference في العنصر FoodCartExtension عند الدفع:

  • PickupInfo.pickupTimeIso8601
  • DeliveryInfo.deliveryTimeIso8601

تنفيذ الطلبات المسبقة عند الدفع

يسرد الجدول أدناه الطرق المحتملة لتنفيذ ردّ التنفيذ أثناء وقت الدفع عندما يحاول المستخدمون تقديم الطلبات.

السيناريو سلوك تلبية الطلبات
يمكن تنفيذ الطلب المسبق للخانة المطلوبة. يجب قبول سلة التسوّق P0M ("في أقرب وقت ممكن") أو FUTURE_SLOT من خلال إنشاء ProposedOrder بالخانة نفسها. للاطّلاع على مثال على استجابة الدفع لقبول خانة، راجِع مقتطف الرمز هذا.
لا يمكن تنفيذ الطلب المسبق للخانة المطلوبة. يجب أن يتّبع الطلب الذي تقدّمه عملية الدفع ما يلي:
  1. ارفض سلة تسوّق P0M أو FUTURE_SLOT المطلوبة، ووضِّح سبب عدم تنفيذ الطلب في العنصر FoodErrorExtension.
    • إذا تعذّر تنفيذ الطلب بسبب الحدّ الأقصى للسعة، حدِّد FoodOrderError لنوع الخطأ NO_CAPACITY.
    • وإذا تعذّر تنفيذ الطلب لأنّ المطعم مغلق، حدِّد FoodOrderError من نوع الخطأ CLOSED.
    • وإذا تعذّر تنفيذ الطلب لسبب آخر، حدِّد FoodOrderError من نوع الخطأ UNAVAILABLE_SLOT.
  2. قدِّم قيم P0M أو FUTURE_SLOT بديلة في correctedProposedOrder إذا أمكن. يجب أن تكون هذه القيم هي جميع الخانات الصالحة لتنفيذ الطلب خلال الأيام السبعة التالية بدءًا من الوقت الحالي. أدرِج الخانة P0M متى أمكن.

للاطّلاع على مثال على استجابة دفع تقترح خانات بديلة، يمكنك الاطّلاع على مقتطف الرمز هذا.

الخانات البديلة لتنفيذ الطلبات

عند الدفع، إذا كانت الخانات التي تقترحها Google للطلب المسبق غير مناسبة، يمكن أن تقترح عليك طريقة التنفيذ بدائل باستخدام الكائن CheckoutResponseMessage.

لتحديد خانات طلبات مسبقة بديلة، يمكنك الردّ على طلب الدفع باستخدام FoodErrorExtension وضبط القيم التالية:

  1. في المَعلمة foodOrderErrors، حدِّد نوع الخطأ (مثل UNAVAILABLE_SLOT أو NO_CAPACITY أو CLOSED).
  2. في المعلَمة correctedProposedOrder، قدِّم قيم P0M أو FUTURE_SLOT بديلة من خلال availableFulfillmentOptions.

يجب أن تكون الخانات البديلة متاحة لمدة 7 أيام تالية من وقت تقديم الطلب، وأن تتضمّن جميع الخانات التي يمكن فيها توصيل سلة التسوّق التي طلبها المستخدم.

على سبيل المثال، لنفترض أنّ عروض الغداء الخاصة متاحة فقط من الاثنين إلى الجمعة من الساعة 11 صباحًا إلى 1 بعد الظهر. بعد ذلك، يحاول المستخدم إضافة عروض الغداء الخاصة إلى عربة التسوق ولكن الخانة المحددة غير متاحة. في هذه الحالة، يجب أن تحتفظ عملية توصيل الطلبات بالعروض الخاصة للغداء في عربة التسوق، وأن تُظهر فقط خانات مواعيد الساعة 11 صباحًا إلى الساعة 1 مساءً للأيام السبعة المقبلة

يجب حذف الكائن correctedProposedOrder.Cart.fulfillmentPreference في استجابتك.

إذا لم تكن هناك خانات متاحة، أو إذا كان المطعم أو الخدمة لا يتيحان الطلبات المُسبقة، ليس عليك تقديم correctedProposedOrder.

يمكنك الاطّلاع أدناه على الأمثلة حول رسائل JSON التي يتم عرضها بين توصيل الطلبات وGoogle أثناء عملية الدفع وطلب الردّ على الطلبات المسبَقة، وعندما يكون المطعم أو الخدمة متاحًا لتلقّي الطلبات المُسبقة.

مثال: CheckoutRequest مع خانة التسليم

يُظهر المقتطف أدناه مثالاً لطلب دفع يتضمن خانة تسليم الطلب المتقدم.

{
  "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": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

مثال: قبول CheckoutResponse للخانة

يعرض المقتطف أدناه مثالاً لاستجابة الدفع حيث يقبل تنفيذك الخانات المقترحة للطلبات المسبقة.

{
  "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": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

مثال: CheckoutResponse مع خانات بديلة

يعرض المقتطف أدناه مثالاً لاستجابة الدفع حيث يقترح تنفيذك خانات طلب مسبقة بديلة. يُرجى العِلم أنّه يجب حذف الكائن 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": {
                ...
              }
            }
          }
        }
      ]
    }
  }
}

تنفيذ الطلبات المسبقة عند إرسال الطلب

عند إرسال الطلب، في حال حدوث مشكلة في خانات الطلبات المسبقة، يجب أن يتضمّن SubmitOrderResponseMessage السبب (مثل UNAVAILABLE_SLOT أو UNKNOWN) في العنصر RejectionInfo.

يمكنك تعديل حالة الطلب من CREATED إلى CONFIRMED في العنصر OrderState عندما يقبل مقدِّم الطلب الطلب. أدرِج الفترة الزمنية المحدّدة في رسالة التأكيد الإلكترونية إلى المستخدم.

إذا أرسلت طريقة التنفيذ الطلب إلى المطعم في وقت لاحق، أرسِل تحديثًا إلى Google باستخدام إجراء تعديل الطلب غير المتزامن.

في عنصر OrderUpdate من الردّ على الطلب المُرسَل في عملية التنفيذ أو التعديلات اللاحقة غير المتزامنة للطلب، يمكنك تضمين estimatedFulfillmentTimeIso8601 مع ضبط القيمة على النحو التالي:

  • عندما تكون حالة الطلب CREATED أو CONFIRMED، اضبط القيمة على وقت التسليم أو الاستلام الذي حدّده المستخدم للطلب المسبق.
  • عندما يتوفر وقت تقديري أكثر دقة للتسليم من المطعم أو الخدمة، اضبط القيمة على الوقت المقدر للتسليم أو وقت الاستلام.

مثال: SubmitOrderRequest مع فترة التسليم

يُظهر المقتطف أدناه مثالاً لطلب إرسال يشير إلى خانة الطلب المتقدمة التي اختارها المستخدم.

{
  "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": {
                ...
              }
            }
          }
        }
      ]
    }
  ]
}

مثال: قبول الطلب بواسطة SendOrderResponse

يعرض المقتطف أدناه مثالاً لاستجابة طلب يؤكّد إتمامك فيه قبول الطلب المقدّم للمستخدم.

{
  "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"
              }
            }
          }
        }
      ]
    }
  }
}

مثال: يتم رفض الطلب بواسطة SendOrderResponse بسبب عدم توفُّر الخانة

يعرض المقتطف أدناه مثالاً لاستجابة طلب يتم فيها رفض تنفيذ الطلب المقدّم من المستخدم بسبب عدم توفر خانة.

{
  "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": [
                ...
              ]
            }
          }
        }
      ]
    }
  }
}

أمثلة على الطلبات المتقدّمة

يمكن استخدام النوع AdvanceServiceDeliveryHoursSpecification لتحديد ساعات التسليم أو الاستلام للمستخدمين لجدولة طلبهم مسبقًا.

ملاحظة: هناك فترتان زمنيتان منفصلتان يجب تحديدهما لتنفيذ الخدمة: فترة الطلب التي تحدّد الوقت الذي يمكن للمستخدمين فيه تقديم الطلب، وفترة التنفيذ التي تحدّد وقت توصيل الطلب. يحدّد الكائن OpeningHoursSpecification الوقت الذي يمكن فيه للمستخدِم تقديم الطلب. وتحدِّد أوقات تنفيذ الطلب الفرعية (ServiceDeliveryHoursSpecification أو AdvanceServiceDeliveryHoursSpecification) متى يمكن تنفيذ الطلب.

يحدد المثال التالي ساعات الخدمة لقبول الطلبات المسبقة، مع فواصل خدمة مدتها 15 دقيقة.

{
  "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"
          }
        }
      ]
    }
  ]
}

يوضح المثال التالي كيف يمكنك تحديد أن الخدمة مفتوحة للطلبات في اليوم نفسه في يوم عيد الميلاد ولكنها مغلقة للطلبات المتقدمة المجدولة لهذا اليوم. يدعم هذا المثال السيناريوهات التالية:

  • يمكن للمستخدمين تقديم طلب يوم 25 كانون الأول (ديسمبر) للتسليم في اليوم نفسه.
  • يمكن للمستخدمين تقديم طلب مسبق بتاريخ 25 كانون الأول (ديسمبر) للتسليم في 27 كانون الأول (ديسمبر).
  • لا يمكن للمستخدمين تقديم طلب مسبق بتاريخ 22 كانون الأول (ديسمبر) لتسليمه في 25 كانون الأول (ديسمبر).
{
  "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"
  }
}

يوضح المثال التالي كيف يمكنك تحديد أن الخدمة مغلقة للطلبات في اليوم نفسه أو الطلبات المسبقة المجدولة ليوم عيد الميلاد، ولكن مفتوحة للطلبات المتقدمة المجدولة في يوم لاحق. يدعم هذا المثال السيناريوهات التالية:

  • لا يمكن للمستخدمين تقديم طلب في 25 كانون الأول (ديسمبر) للتسليم في اليوم نفسه.
  • يمكن للمستخدمين تقديم طلب مسبق بتاريخ 25 كانون الأول (ديسمبر) للتسليم في 27 كانون الأول (ديسمبر).
  • لا يمكن للمستخدمين تقديم طلب مسبق بتاريخ 22 كانون الأول (ديسمبر) لتسليمه في 25 كانون الأول (ديسمبر).
{
  "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"
    }
  ]
}

يقبل النموذج التالي للخدمة الطلبات على مدار 24 ساعة طوال أيام الأسبوع، ويتم تسليمه من الساعة 10 صباحًا إلى الساعة 2:59:59 بعد الظهر خلال أيام الأسبوع:

...
{
  "@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"
    }
  }
}
...

تقبل الخدمة النموذجية التالية الطلبات كل يوم من الساعة 8 صباحًا إلى الساعة 4:59:59 مساءً، ويمكن للعملاء اختيار التسليم في غضون ساعة أو اختيار إحدى الشرائح:

...
{
  "@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"
      }
    }
  ]
}
...

يعرض النموذج التالي حالة يفتح فيها المتجر من الساعة 8 صباحًا إلى 4:59:59 مساءً في أيام الأسبوع ولكن من 8 صباحًا إلى 6:59 مساءً في عطلات نهاية الأسبوع. لا يتم قبول الطلبات على مدار 24 ساعة طوال أيام الأسبوع.

...
{
  // 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"
      }
    }
  ]
}
...