Tính năng đặt hàng trước phiên bản 1

Bạn có thể hỗ trợ thêm trong phương thức thực hiện của mình để người dùng lên lịch trước cho các đơn đặt hàng tự đến lấy và giao đồ ăn. Trước khi triển khai tính năng hỗ trợ này trong phương thức thực hiện, hãy tạo một nguồn cấp dữ liệu khoảng không quảng cáo dịch vụ chỉ định giờ để người dùng đặt hàng trước, như mô tả trong giản đồ nguồn cấp dữ liệu kho hàng (AdvanceServiceDeliveryHoursSpecification).

Khung giờ đặt hàng trước

Google đề xuất khung giờ đặt hàng trước theo mức tăng 15 phút (tối đa 7 ngày trước đó) dựa trên thời gian thực hiện đơn hàng của một nhà hàng hoặc dịch vụ (như xác định trong AdvanceServiceDeliveryHoursSpecification).

Để truy xuất thời điểm đề xuất cho đơn đặt hàng trước, hãy sử dụng các giá trị sau từ trường fulfillmentPreference của đối tượng FoodCartExtension ở bước thanh toán:

  • PickupInfo.pickupTimeIso8601
  • DeliveryInfo.deliveryTimeIso8601

Triển khai đơn đặt hàng trước khi thanh toán

Bảng dưới đây liệt kê các cách mà bạn có thể triển khai phản hồi của phương thức thực hiện đơn hàng tại thời điểm thanh toán khi người dùng cố gắng đặt hàng.

Trường hợp Hành vi thực hiện đơn hàng
Đơn đặt hàng trước có thể được thực hiện cho vị trí được yêu cầu. Chấp nhận giỏ hàng P0M ("càng sớm càng tốt") hoặc FUTURE_SLOT bằng cách tạo một ProposedOrder có cùng một ô. Để biết ví dụ về phản hồi thanh toán chấp nhận vị trí, hãy xem đoạn mã này.
Không thể thực hiện đơn đặt hàng trước cho vị trí được yêu cầu. Phương thức thực hiện của bạn phải thực hiện những việc sau:
  1. Từ chối giỏ hàng P0M hoặc FUTURE_SLOT được yêu cầu và cho biết lý do không thể thực hiện đơn đặt hàng trong đối tượng FoodErrorExtension.
    • Nếu không thể thực hiện đơn đặt hàng do hạn mức, hãy chỉ định FoodOrderError thuộc loại lỗi NO_CAPACITY.
    • Nếu không thể thực hiện đơn đặt hàng do nhà hàng đã đóng cửa, hãy chỉ định FoodOrderError thuộc loại lỗi CLOSED.
    • Nếu không thể thực hiện đơn đặt hàng vì một số lý do khác, hãy chỉ định FoodOrderError thuộc loại lỗi UNAVAILABLE_SLOT.
  2. Nếu có thể, hãy cung cấp giá trị thay thế P0M hoặc FUTURE_SLOT trong correctedProposedOrder. Những giá trị này phải là tất cả vị trí thực hiện đơn hàng hợp lệ trong 7 ngày tiếp theo kể từ thời điểm hiện tại. Thêm vùng P0M bất cứ khi nào có thể.

Để biết ví dụ về phản hồi thanh toán đề xuất các vị trí thay thế, hãy xem đoạn mã này.

Vị trí thay thế để thực hiện đơn đặt hàng

Khi thanh toán, nếu các vị trí đặt hàng trước do Google đề xuất không phù hợp, thì phương thức thực hiện của bạn có thể đề xuất các lựa chọn thay thế bằng cách sử dụng đối tượng CheckoutResponseMessage.

Để chỉ định khung giờ cho đơn đặt hàng trước thay thế, hãy phản hồi yêu cầu thanh toán bằng FoodErrorExtension và đặt các giá trị sau:

  1. Trong tham số foodOrderErrors, hãy chỉ định loại lỗi (chẳng hạn như UNAVAILABLE_SLOT, NO_CAPACITY hoặc CLOSED).
  2. Trong tham số correctedProposedOrder, hãy cung cấp các giá trị P0M hoặc FUTURE_SLOT thay thế thông qua availableFulfillmentOptions.

Các vị trí thay thế nên là trong 7 ngày tiếp theo kể từ thời điểm đặt hàng và bao gồm tất cả các vị trí mà giỏ hàng mà người dùng yêu cầu có thể được thực hiện.

Ví dụ: giả sử giá đặc biệt cho bữa trưa chỉ có từ thứ Hai đến thứ Sáu, từ 11 giờ sáng đến 1 giờ chiều. Sau đó, người dùng thử thêm các món ăn trưa đặc biệt vào giỏ hàng nhưng không gian họ đã chọn không có sẵn. Trong trường hợp này, phương thức thực hiện của bạn sẽ giữ lại các món ăn trưa đặc biệt trong giỏ hàng và chỉ trả lại khung giờ 11 giờ sáng đến 1 giờ chiều trong 7 ngày tới

Bạn nên bỏ qua đối tượng correctedProposedOrder.Cart.fulfillmentPreference trong phản hồi.

Nếu không còn suất trống hoặc nếu nhà hàng hoặc dịch vụ không hỗ trợ đặt hàng trước, thì bạn không cần cung cấp correctedProposedOrder.

Hãy xem ví dụ dưới đây về thông báo JSON giữa phương thức thực hiện đơn hàng của bạn và Google trong quá trình yêu cầu thanh toán và phản hồi cho một đơn đặt hàng trước, khi nhà hàng hoặc dịch vụ cho phép nhận đơn đặt hàng trước.

Ví dụ: CheckoutRequest có vị trí phân phối

Đoạn mã dưới đây cho thấy ví dụ về yêu cầu thanh toán có khung giao hàng trước.

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

Ví dụ: CheckoutResponse chấp nhận vị trí

Đoạn mã dưới đây cho thấy ví dụ về phản hồi thanh toán, trong đó phương thức thực hiện của bạn chấp nhận các vị trí đặt hàng trước được đề xuất.

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

Ví dụ: CheckoutResponse với các khung giờ thay thế

Đoạn mã dưới đây cho thấy ví dụ về một phản hồi thanh toán, trong đó phương thức thực hiện của bạn đề xuất các khung giờ cho đơn đặt hàng trước thay thế. Xin lưu ý rằng bạn nên bỏ qua đối tượng correctedProposedOrder.Cart.fulfillmentPreference trong phản hồi.

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

Triển khai đơn đặt hàng trước khi gửi đơn đặt hàng

Khi gửi đơn đặt hàng, nếu có vấn đề về thời điểm đặt hàng trước, SubmitOrderResponseMessage của bạn phải bao gồm lý do (chẳng hạn như UNAVAILABLE_SLOT hoặc UNKNOWN) trong đối tượng RejectionInfo.

Cập nhật trạng thái của đơn đặt hàng từ CREATED thành CONFIRMED trong đối tượng OrderState khi nhà cung cấp chấp nhận đơn đặt hàng. Đưa khung giờ đã chọn vào email xác nhận gửi cho người dùng.

Nếu phương thức thực hiện của bạn gửi đơn đặt hàng đến nhà hàng sau đó, hãy gửi cho Google thông tin cập nhật bằng cách sử dụng Thao tác cập nhật đơn đặt hàng không đồng bộ.

Trong đối tượng OrderUpdate của phản hồi đơn đặt hàng gửi của phương thức thực hiện hoặc các lần cập nhật đơn đặt hàng không đồng bộ tiếp theo, hãy thêm estimatedFulfillmentTimeIso8601 có giá trị được đặt như sau:

  • Khi trạng thái đơn đặt hàng là CREATED hoặc CONFIRMED, hãy đặt giá trị thành thời gian giao hàng hoặc đến lấy hàng mà người dùng đã lên lịch cho đơn đặt hàng trước.
  • Khi có thời gian giao hàng dự kiến của nhà hàng hoặc dịch vụ chính xác hơn, hãy đặt giá trị thành thời gian dự kiến cho thời gian giao hàng hoặc lấy hàng.

Ví dụ: SubmitOrderRequest có vùng phân phối

Đoạn mã dưới đây cho thấy ví dụ về một yêu cầu gửi đơn đặt hàng cho biết vị trí đặt hàng trước mà người dùng đã chọn.

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

Ví dụ: SubmitOrderResponse chấp nhận đơn đặt hàng

Đoạn mã dưới đây cho thấy ví dụ về một phản hồi gửi đơn đặt hàng, trong đó việc thực hiện đơn hàng xác nhận rằng họ đã chấp nhận đơn đặt hàng trước của người dùng.

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

Ví dụ: SubmitOrderResponse từ chối đơn đặt hàng vì không có vị trí

Đoạn mã dưới đây cho thấy ví dụ về một phản hồi gửi đơn đặt hàng, trong đó việc thực hiện đơn hàng của bạn từ chối đơn đặt hàng trước của người dùng vì không còn một suất nữa.

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

Ví dụ về đơn đặt hàng trước

Bạn có thể sử dụng loại AdvanceServiceDeliveryHoursSpecification để chỉ định giờ giao hàng hoặc giờ đến lấy hàng để người dùng lên lịch trước cho đơn đặt hàng.

Lưu ý: Có hai khoảng thời gian riêng biệt mà bạn phải chỉ định cho việc thực hiện đơn hàng: thời hạn đặt hàng chỉ định thời điểm người dùng có thể đặt hàng và thời lượng thực hiện đơn hàng chỉ định thời điểm thực hiện đơn đặt hàng. Đối tượng OpeningHoursSpecification xác định thời điểm người dùng có thể đặt hàng. Thời gian thực hiện đơn hàng con (ServiceDeliveryHoursSpecification hoặc AdvanceServiceDeliveryHoursSpecification) xác định thời điểm có thể thực hiện đơn đặt hàng.

Ví dụ sau đây xác định giờ của một dịch vụ để chấp nhận đơn đặt hàng trước, với khoảng thời gian dịch vụ là 15 phút.

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

Ví dụ sau cho thấy cách bạn có thể chỉ định rằng dịch vụ mở cửa cho các đơn đặt hàng trong cùng ngày vào ngày Giáng sinh nhưng đóng cửa đối với các đơn đặt hàng nâng cao được lên lịch cho ngày đó. Ví dụ này hỗ trợ các trường hợp sau:

  • Người dùng có thể đặt hàng vào ngày 25 tháng 12 để được giao hàng trong cùng ngày.
  • Người dùng có thể đặt hàng trước vào ngày 25 tháng 12 để giao hàng theo lịch vào ngày 27 tháng 12.
  • Người dùng không thể đặt hàng trước vào ngày 22 tháng 12 để giao hàng theo lịch vào ngày 25 tháng 12.
{
  "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"
  }
}

Ví dụ sau cho thấy cách bạn có thể chỉ định rằng dịch vụ đóng cửa đối với các đơn đặt hàng cùng ngày hoặc các đơn đặt hàng đặt trước được lên lịch vào ngày Giáng sinh, nhưng vẫn mở đối với các đơn đặt hàng nâng cao được lên lịch vào một ngày sau đó. Ví dụ này hỗ trợ các trường hợp sau:

  • Người dùng không thể đặt hàng vào ngày 25 tháng 12 để giao hàng trong cùng ngày.
  • Người dùng có thể đặt hàng trước vào ngày 25 tháng 12 để giao hàng theo lịch vào ngày 27 tháng 12.
  • Người dùng không thể đặt hàng trước vào ngày 22 tháng 12 để giao hàng theo lịch vào ngày 25 tháng 12.
{
  "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"
    }
  ]
}

Dịch vụ mẫu sau đây chấp nhận đơn đặt hàng 24x7 và giao hàng từ 10:00 đến 2:59:59 vào các ngày trong tuần:

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

Dịch vụ mẫu sau đây chấp nhận đơn đặt hàng mỗi ngày từ 8 giờ sáng đến 4:59:59 tối, và khách hàng có thể chọn giao hàng trong vòng một giờ hoặc chọn một trong các khung giờ:

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

Mẫu sau đây cho thấy trường hợp cửa hàng mở cửa từ 8 giờ sáng đến 4:59:59 tối vào các ngày trong tuần nhưng từ 8 giờ sáng đến 6:59 tối vào cuối tuần. Không chấp nhận đơn đặt hàng 24x7.

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