Initial push of test utility
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..94809b7
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,2 @@
+Unfortunately, given the nature of the tools provided here, we do not
+accept contributions.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1fe2cdf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,83 @@
+# Maps Booking
+
+This repo contains tools and code samples for partners that wish to integrate
+with [Reserve](https://www.google.com/maps/reserve/)
+
+## Testing Client
+
+Before using the test utility, the Go programming language must be installed
+on your workstation. A precompiled Go binary for your operating system can
+be [found here](https://golang.org/dl/)
+
+This guide will assume you're using the default GOPATH and subsequent GOBIN.
+For a comprehensive explanation of the GOPATH env variable please see
+[this document](https://golang.org/dl/) by the Go team.
+
+### Installing the utility
+
+First, build your Go directory structure. A comprehensive guide on the intended
+structure of Go code can be [found here.](https://golang.org/doc/code.html)
+
+ mkdir -p $HOME/go/bin $HOME/go/pkg $HOME/go/src/github.com/maps-booking
+
+Next, retrieve the utility from the
+[maps-booking repository](https://maps-booking.googlesource.com/)
+
+ git clone https://maps-booking.googlesource.com/test_client $HOME/go/src/github.com/maps-booking/
+
+Lastly, download all dependencies and install the tool.
+
+ go get -d $HOME/go/...
+ go install $HOME/go/src/github.com/maps-booking/testclient/main.go
+
+### Using the utility
+
+After following the install steps above an executable should now live in
+
+ $HOME/go/bin/main
+
+All available flags can be displayed using the '--help' flag. The currently
+accepted flags are:
+
+ -all_tests
+ Whether to test all endpoints.
+ -availability_feed string
+ Absolute path to availability feed required for all tests except health.
+ Feeds can be in either json or pb3 format
+ -booking_status_test
+ Whether to test the GetBookingStatus endpoint.
+ -booking_test
+ Whether to test the CreateBooking endpoint.
+ -check_availability_test
+ Whether to test the CheckAvailability endpoint.
+ -health_check_test
+ Whether to test the Health endpoint.
+ -list_bookings_test
+ Whether to test the ListBookings endpoint
+ -num_test_slots int
+ Maximum number of slots to test from availability_feed.
+ Slots will be selected randomly (default 10)
+ -output_dir string
+ Absolute path of dir to dump log file.
+ -rescheduling_test
+ Whether to test the UpdateBooking endpoint.
+ -rpc_timeout duration
+ Number of seconds to wait before abandoning request (default 30s)
+ -server_addr string
+ Your grpc server's address in the format of
+ host:port (default "example.com:80")
+
+Example Usage:
+
+ bin/main -health_check_test=true -check_availability_test=true
+ -output_dir="/tmp" -server_addr="localhost:50051”
+ -availability_feed="/tmp/test.json"
+
+### Parsing the output
+
+The test utility will output a file with the prefix 'grpc_test_client_log_'
+followed by a timestamp in RFC3339 format. The output file contains a
+complete log of all Requests and Responses sent/received by the testing tool as
+well as diffs of the expected response in the event of errors.
+Similar to a compiler, an overview of the entire run can be found at the end
+of the file for user friendly digestion.
diff --git a/api/api.go b/api/api.go
new file mode 100644
index 0000000..4379df2
--- /dev/null
+++ b/api/api.go
@@ -0,0 +1,281 @@
+/*
+Copyright 2017 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package api contains validation wrappers over BookingService endpoints.
+package api
+
+import (
+ "errors"
+ "fmt"
+ "log"
+ "sort"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes"
+ "github.com/google/go-cmp/cmp"
+ "github.com/maps-booking/utils"
+ "golang.org/x/net/context"
+ "google.golang.org/genproto/protobuf/field_mask"
+ "google.golang.org/grpc"
+
+ mpb "github.com/maps-booking/bookingservice"
+ fpb "github.com/maps-booking/feeds"
+ hpb "google.golang.org/grpc/health/grpc_health_v1"
+)
+
+const (
+ userID = "0"
+ firstName = "Jane"
+ lastName = "Doe"
+ telephone = "+18007897890"
+ email = "test@example.com"
+ service = "ext.maps.booking.partner.v2.BookingService"
+)
+
+// Bookings is a convenience type for a booking array.
+type Bookings []*mpb.Booking
+
+func (b Bookings) Len() int {
+ return len(b)
+}
+
+func (b Bookings) Less(i, j int) bool {
+ return b[i].GetBookingId() < b[j].GetBookingId()
+}
+
+func (b Bookings) Swap(i, j int) {
+ b[i], b[j] = b[j], b[i]
+}
+
+// HealthCheck performs a gRPC health check.
+func HealthCheck(ctx context.Context, conn *grpc.ClientConn) error {
+ utils.LogFlow("Health Check", "Start")
+ defer utils.LogFlow("Health Check", "End")
+
+ healthCli := hpb.NewHealthClient(conn)
+ req := &hpb.HealthCheckRequest{Service: service}
+ // Ignore cancel. Server will take care of it.
+ resp, err := healthCli.Check(ctx, req)
+ if err != nil {
+ return fmt.Errorf("could not complete health check: %v", err)
+ }
+
+ if diff := cmp.Diff(resp.Status, hpb.HealthCheckResponse_SERVING); diff != "" {
+ return fmt.Errorf("health check invalid (-got +want)\n%s", diff)
+ }
+ log.Println("health check success!")
+ return nil
+}
+
+// CheckAvailability beforms a maps booking availability check on all supplied availability slots. This function
+// will return all slots with a valid return.
+func CheckAvailability(ctx context.Context, a *fpb.Availability, c mpb.BookingServiceClient) error {
+ slot, err := utils.BuildSlotFrom(a)
+ if err != nil {
+ return fmt.Errorf("unable to build request for check availability flow. err: %v, availability record: %v", err, a.String())
+ }
+
+ req := &mpb.CheckAvailabilityRequest{
+ Slot: slot,
+ }
+
+ log.Printf("CheckAvailability Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.CheckAvailability(ctx, req)
+ if err != nil {
+ return fmt.Errorf("invalid response. CheckAvailability yielded error: %v", err)
+ }
+
+ log.Printf("CheckAvailability Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ if diff := cmp.Diff(resp.GetSlot(), req.GetSlot(), cmp.Comparer(proto.Equal)); diff != "" {
+ return fmt.Errorf("invalid response. CheckAvailability slots differ (-got +want)\n%s", diff)
+ }
+
+ if resp.GetCountAvailable() == 0 {
+ return errors.New("no count available in response")
+ }
+
+ return nil
+}
+
+// CreateBooking attempts to create bookings from availability slots.
+func CreateBooking(ctx context.Context, a *fpb.Availability, c mpb.BookingServiceClient) (*mpb.Booking, error) {
+ slot, err := utils.BuildSlotFrom(a)
+ if err != nil {
+ return nil, fmt.Errorf("unable to build request for check availability flow. err: %v, availability record: %v", err, a.String())
+ }
+ // Lease currently unsupported.
+ req := &mpb.CreateBookingRequest{
+ Slot: slot,
+ UserInformation: &mpb.UserInformation{
+ UserId: userID,
+ GivenName: firstName,
+ FamilyName: lastName,
+ Telephone: telephone,
+ Email: email,
+ },
+ PaymentInformation: &mpb.PaymentInformation{
+ PrepaymentStatus: mpb.PrepaymentStatus_PREPAYMENT_NOT_PROVIDED,
+ },
+ IdempotencyToken: utils.BuildIdempotencyToken(a, userID),
+ }
+
+ log.Printf("CreateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.CreateBooking(ctx, req)
+ if err != nil {
+ return nil, fmt.Errorf("invalid response. CreateBooking yielded error: %v", err)
+ }
+
+ log.Printf("CreateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ if resp.GetBookingFailure() != nil {
+ return nil, fmt.Errorf("invalid response. CreateBooking failed with booking failure %v", resp.GetBookingFailure())
+ }
+
+ b := resp.GetBooking()
+ if iE := utils.ValidateBooking(b, &mpb.Booking{
+ Slot: req.GetSlot(),
+ UserInformation: req.GetUserInformation(),
+ PaymentInformation: req.GetPaymentInformation(),
+ }); iE != nil {
+ return nil, fmt.Errorf("invalid response. CreateBooking invalid: %s", iE.Error())
+ }
+ return b, nil
+}
+
+// ListBookings calls the maps booking ListBookings rpc and compares the return with all input bookings.
+func ListBookings(ctx context.Context, tB Bookings, c mpb.BookingServiceClient) (Bookings, error) {
+ var out Bookings
+ req := &mpb.ListBookingsRequest{
+ UserId: userID,
+ }
+ log.Printf("ListBookings Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.ListBookings(ctx, req)
+ if err != nil {
+ return out, fmt.Errorf("invalid response. ListBookings yielded error: %v. Abandoning all booking from this flow", err)
+ }
+
+ log.Printf("ListBookings Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ gB := Bookings(resp.GetBookings())
+ if len(gB) != len(tB) {
+ return out, fmt.Errorf("number of bookings differ, ListBookings invalid. Got: %d, Want: %d. Abandoning all bookings from this flow", len(gB), len(tB))
+ }
+
+ sort.Sort(gB)
+ sort.Sort(tB)
+ for i := 0; i < len(tB); i++ {
+ if iE := utils.ValidateBooking(gB[i], tB[i]); iE != nil {
+ log.Printf("ListBookings invalid, %s, abandoning slot %d/%d", iE.Error(), i, len(tB))
+ continue
+ }
+ out = append(out, tB[i])
+ }
+
+ return out, nil
+}
+
+// GetBookingStatus checks that all input bookings are in an acceptable state.
+func GetBookingStatus(ctx context.Context, b *mpb.Booking, c mpb.BookingServiceClient) error {
+ req := &mpb.GetBookingStatusRequest{
+ BookingId: b.GetBookingId(),
+ }
+
+ log.Printf("GetBookingStatus Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.GetBookingStatus(ctx, req)
+ if err != nil {
+ return fmt.Errorf("invalid response. GetBookingStatus yielded error: %v", err)
+ }
+
+ log.Printf("GetBookingStatus Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ if diff := cmp.Diff(resp.GetBookingStatus(), mpb.BookingStatus_CONFIRMED); diff != "" {
+ return fmt.Errorf("invalid response. BookingStatus differ (-got +want)\n%s", diff)
+ }
+
+ return nil
+}
+
+// CancelBooking is a clean up method that cancels all supplied bookings.
+func CancelBooking(ctx context.Context, b *mpb.Booking, c mpb.BookingServiceClient) error {
+ b.Status = mpb.BookingStatus_CANCELED
+ req := &mpb.UpdateBookingRequest{
+ UpdateMask: &field_mask.FieldMask{
+ Paths: []string{"status"},
+ },
+ Booking: b,
+ }
+
+ log.Printf("UpdateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.UpdateBooking(ctx, req)
+ if err != nil {
+ return fmt.Errorf("invalid response. UpdateBooking yielded error: %v", err)
+ }
+
+ log.Printf("UpdateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ if iE := utils.ValidateBooking(resp.GetBooking(), req.GetBooking()); iE != nil {
+ return fmt.Errorf("invalid response. UpdateBooking: %s", iE.Error())
+ }
+ return nil
+}
+
+// Rescheduling will attempt to create a booking, update the booking, then cancel.
+func Rescheduling(ctx context.Context, av []*fpb.Availability, c mpb.BookingServiceClient) error {
+ var slots []*fpb.Availability
+ for _, v := range utils.BuildMerchantServiceMap(av) {
+ // Need at least two slots for reschedule.
+ if len(v) <= 1 {
+ continue
+ }
+ slots = v
+ break
+ }
+
+ if len(slots) == 0 {
+ return errors.New("no suitable availability for rescheduling flow. exiting")
+ }
+ // Book first slot.
+ newBooking, err := CreateBooking(ctx, slots[0], c)
+ if err != nil {
+ return fmt.Errorf("could not complete booking, abandoning rescheduling flow: %v", err)
+ }
+
+ slot := newBooking.GetSlot()
+ // New slot.
+ lastAvailability := slots[len(slots)-1]
+ startTime, err := ptypes.TimestampProto(time.Unix(lastAvailability.GetStartSec(), 0))
+ if err != nil {
+ return fmt.Errorf("could not complete update, abandoning rescheduling flow: %v", err)
+ }
+ slot.StartTime = startTime
+ slot.Duration = ptypes.DurationProto(time.Duration(lastAvailability.GetDurationSec()) * time.Second)
+
+ req := &mpb.UpdateBookingRequest{
+ UpdateMask: &field_mask.FieldMask{
+ Paths: []string{"slot.start_time", "slot.duration"},
+ },
+ Booking: newBooking,
+ }
+
+ log.Printf("UpdateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
+ resp, err := c.UpdateBooking(ctx, req)
+ if err != nil {
+ return fmt.Errorf("invalid response. UpdateBooking yielded error: %v", err)
+ }
+
+ log.Printf("UpdateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
+ if iE := utils.ValidateBooking(resp.GetBooking(), newBooking); iE != nil {
+ return fmt.Errorf("invalid response. UpdateBooking: %s, abandoning slot 1/1", iE.Error())
+ }
+ return CancelBooking(ctx, resp.GetBooking(), c)
+}
diff --git a/bookingservice/booking_service.pb.go b/bookingservice/booking_service.pb.go
new file mode 100644
index 0000000..92b93d4
--- /dev/null
+++ b/bookingservice/booking_service.pb.go
@@ -0,0 +1,1940 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: booking_service.proto
+
+/*
+Package ext_maps_booking_partner_v2 is a generated protocol buffer package.
+
+It is generated from these files:
+ booking_service.proto
+
+It has these top-level messages:
+ Slot
+ Lease
+ LeaseReference
+ Booking
+ UserInformation
+ PostalAddress
+ PaymentProcessingParameters
+ Price
+ UserPaymentOption
+ PaymentInformation
+ BookingFailure
+ Resources
+ CheckAvailabilityRequest
+ CheckAvailabilityResponse
+ CreateLeaseRequest
+ CreateLeaseResponse
+ CreateBookingRequest
+ CreateBookingResponse
+ UpdateBookingRequest
+ UpdateBookingResponse
+ GetBookingStatusRequest
+ GetBookingStatusResponse
+ ListBookingsRequest
+ ListBookingsResponse
+*/
+package ext_maps_booking_partner_v2
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import google_protobuf "github.com/golang/protobuf/ptypes/duration"
+import google_protobuf1 "google.golang.org/genproto/protobuf/field_mask"
+import google_protobuf2 "github.com/golang/protobuf/ptypes/timestamp"
+
+import (
+ context "golang.org/x/net/context"
+ grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type PaymentOptionType int32
+
+const (
+ PaymentOptionType_PAYMENT_OPTION_TYPE_UNSPECIFIED PaymentOptionType = 0
+ PaymentOptionType_PAYMENT_OPTION_SINGLE_USE PaymentOptionType = 1
+ PaymentOptionType_PAYMENT_OPTION_MULTI_USE PaymentOptionType = 2
+ PaymentOptionType_PAYMENT_OPTION_UNLIMITED_USE PaymentOptionType = 3
+)
+
+var PaymentOptionType_name = map[int32]string{
+ 0: "PAYMENT_OPTION_TYPE_UNSPECIFIED",
+ 1: "PAYMENT_OPTION_SINGLE_USE",
+ 2: "PAYMENT_OPTION_MULTI_USE",
+ 3: "PAYMENT_OPTION_UNLIMITED_USE",
+}
+var PaymentOptionType_value = map[string]int32{
+ "PAYMENT_OPTION_TYPE_UNSPECIFIED": 0,
+ "PAYMENT_OPTION_SINGLE_USE": 1,
+ "PAYMENT_OPTION_MULTI_USE": 2,
+ "PAYMENT_OPTION_UNLIMITED_USE": 3,
+}
+
+func (x PaymentOptionType) String() string {
+ return proto.EnumName(PaymentOptionType_name, int32(x))
+}
+func (PaymentOptionType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+// Status of a booking.
+//
+// Updating booking status does not change the status of the associated payment.
+// Prepayment status updates should be done using the PrepaymentStatus enum.
+//
+// nextID: 6
+type BookingStatus int32
+
+const (
+ // Not specified.
+ BookingStatus_BOOKING_STATUS_UNSPECIFIED BookingStatus = 0
+ // Booking has been confirmed
+ BookingStatus_CONFIRMED BookingStatus = 1
+ // Booking is awaiting confirmation by the merchant before it can transition
+ // into CONFIRMED status
+ BookingStatus_PENDING_MERCHANT_CONFIRMATION BookingStatus = 2
+ // Booking has been canceled on behalf of the user.
+ // The merchant can still trigger a manual refund.
+ BookingStatus_CANCELED BookingStatus = 3
+ // User did not show for the appointment
+ BookingStatus_NO_SHOW BookingStatus = 4
+ // User did not show for the appointment in violation of the cancellation
+ // policy.
+ BookingStatus_NO_SHOW_PENALIZED BookingStatus = 5
+)
+
+var BookingStatus_name = map[int32]string{
+ 0: "BOOKING_STATUS_UNSPECIFIED",
+ 1: "CONFIRMED",
+ 2: "PENDING_MERCHANT_CONFIRMATION",
+ 3: "CANCELED",
+ 4: "NO_SHOW",
+ 5: "NO_SHOW_PENALIZED",
+}
+var BookingStatus_value = map[string]int32{
+ "BOOKING_STATUS_UNSPECIFIED": 0,
+ "CONFIRMED": 1,
+ "PENDING_MERCHANT_CONFIRMATION": 2,
+ "CANCELED": 3,
+ "NO_SHOW": 4,
+ "NO_SHOW_PENALIZED": 5,
+}
+
+func (x BookingStatus) String() string {
+ return proto.EnumName(BookingStatus_name, int32(x))
+}
+func (BookingStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+// Prepayment status of a booking.
+// Updating payment status will trigger an update on the payment status of the
+// associated booking (if applicable).
+// Currently, the only supported transition is from PREPAYMENT_PROVIDED to
+// PREPAYMENT_REFUNDED, which will initiate a non-reversible refund on the
+// associated payment transaction.
+type PrepaymentStatus int32
+
+const (
+ // Not specified, defaults to PREPAYMENT_NOT_PROVIDED.
+ PrepaymentStatus_PREPAYMENT_STATUS_UNSPECIFIED PrepaymentStatus = 0
+ // The fee for the booking has been paid in advance.
+ PrepaymentStatus_PREPAYMENT_PROVIDED PrepaymentStatus = 1
+ // The fee for the booking has not been paid in advance.
+ PrepaymentStatus_PREPAYMENT_NOT_PROVIDED PrepaymentStatus = 2
+ // The fee was previously PREPAYMENT_PROVIDED but has now been refunded.
+ PrepaymentStatus_PREPAYMENT_REFUNDED PrepaymentStatus = 3
+ // The fee was previously PREPAYMENT_PROVIDED but now has been credited
+ // (user given a UserPaymentOption as a voucher for the booking).
+ // If this is set, the response should also include the updated
+ // UserPaymentOption.
+ PrepaymentStatus_PREPAYMENT_CREDITED PrepaymentStatus = 4
+)
+
+var PrepaymentStatus_name = map[int32]string{
+ 0: "PREPAYMENT_STATUS_UNSPECIFIED",
+ 1: "PREPAYMENT_PROVIDED",
+ 2: "PREPAYMENT_NOT_PROVIDED",
+ 3: "PREPAYMENT_REFUNDED",
+ 4: "PREPAYMENT_CREDITED",
+}
+var PrepaymentStatus_value = map[string]int32{
+ "PREPAYMENT_STATUS_UNSPECIFIED": 0,
+ "PREPAYMENT_PROVIDED": 1,
+ "PREPAYMENT_NOT_PROVIDED": 2,
+ "PREPAYMENT_REFUNDED": 3,
+ "PREPAYMENT_CREDITED": 4,
+}
+
+func (x PrepaymentStatus) String() string {
+ return proto.EnumName(PrepaymentStatus_name, int32(x))
+}
+func (PrepaymentStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+type PaymentProcessingParameters_PaymentProcessor int32
+
+const (
+ PaymentProcessingParameters_PAYMENT_PROCESSOR_UNSPECIFIED PaymentProcessingParameters_PaymentProcessor = 0
+ PaymentProcessingParameters_PROCESSOR_STRIPE PaymentProcessingParameters_PaymentProcessor = 1
+ PaymentProcessingParameters_PROCESSOR_BRAINTREE PaymentProcessingParameters_PaymentProcessor = 2
+)
+
+var PaymentProcessingParameters_PaymentProcessor_name = map[int32]string{
+ 0: "PAYMENT_PROCESSOR_UNSPECIFIED",
+ 1: "PROCESSOR_STRIPE",
+ 2: "PROCESSOR_BRAINTREE",
+}
+var PaymentProcessingParameters_PaymentProcessor_value = map[string]int32{
+ "PAYMENT_PROCESSOR_UNSPECIFIED": 0,
+ "PROCESSOR_STRIPE": 1,
+ "PROCESSOR_BRAINTREE": 2,
+}
+
+func (x PaymentProcessingParameters_PaymentProcessor) String() string {
+ return proto.EnumName(PaymentProcessingParameters_PaymentProcessor_name, int32(x))
+}
+func (PaymentProcessingParameters_PaymentProcessor) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{6, 0}
+}
+
+// Who handles payment processing?
+// If payment is processed by the partner, CreateBooking request will
+// include additional parameters (PaymentProcessingParameters) indicating
+// the payment method to be used to process the payment.
+type PaymentInformation_PaymentProcessedBy int32
+
+const (
+ PaymentInformation_PAYMENT_PROCESSED_BY_UNSPECIFIED PaymentInformation_PaymentProcessedBy = 0
+ PaymentInformation_PROCESSED_BY_GOOGLE PaymentInformation_PaymentProcessedBy = 1
+ PaymentInformation_PROCESSED_BY_PARTNER PaymentInformation_PaymentProcessedBy = 2
+)
+
+var PaymentInformation_PaymentProcessedBy_name = map[int32]string{
+ 0: "PAYMENT_PROCESSED_BY_UNSPECIFIED",
+ 1: "PROCESSED_BY_GOOGLE",
+ 2: "PROCESSED_BY_PARTNER",
+}
+var PaymentInformation_PaymentProcessedBy_value = map[string]int32{
+ "PAYMENT_PROCESSED_BY_UNSPECIFIED": 0,
+ "PROCESSED_BY_GOOGLE": 1,
+ "PROCESSED_BY_PARTNER": 2,
+}
+
+func (x PaymentInformation_PaymentProcessedBy) String() string {
+ return proto.EnumName(PaymentInformation_PaymentProcessedBy_name, int32(x))
+}
+func (PaymentInformation_PaymentProcessedBy) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{9, 0}
+}
+
+type BookingFailure_Cause int32
+
+const (
+ // Default value: Don't use; amounts to an "unknown error"
+ BookingFailure_CAUSE_UNSPECIFIED BookingFailure_Cause = 0
+ // The referenced availability slot is not available any longer.
+ BookingFailure_SLOT_UNAVAILABLE BookingFailure_Cause = 1
+ // The user has already booked an appointment for the referenced
+ // availability slot.
+ BookingFailure_SLOT_ALREADY_BOOKED_BY_USER BookingFailure_Cause = 2
+ // The lease (if provided) has expired and cannot be used any longer to
+ // complete the requested booking.
+ BookingFailure_LEASE_EXPIRED BookingFailure_Cause = 3
+ // The requested cancellation cannot be performed at the current time due
+ // to time restrictions in the merchant's cancellation policy.
+ BookingFailure_OUTSIDE_CANCELLATION_WINDOW BookingFailure_Cause = 4
+ // An error was encountered while processing the payment because the
+ // provided credit card type was not accepted by the merchant. The credit
+ // card type must be supplied in rejected_card_type.
+ BookingFailure_PAYMENT_ERROR_CARD_TYPE_REJECTED BookingFailure_Cause = 5
+ // An error was encountered while processing the payment because the
+ // provided credit card was declined.
+ BookingFailure_PAYMENT_ERROR_CARD_DECLINED BookingFailure_Cause = 6
+ // An error was encountered with the pack/membership used to pay for the
+ // booking. There could be no valid uses left, it could have expired, etc.
+ BookingFailure_PAYMENT_OPTION_NOT_VALID BookingFailure_Cause = 7
+ // An error was encountered while processing the payment for this booking.
+ // Use this value to indicate a general payment related error, only if the
+ // error does not match to a specific payment error above.
+ BookingFailure_PAYMENT_ERROR BookingFailure_Cause = 8
+ // User cannot use the given payment option (e.g. user trying to use a
+ // first time price for the second time).
+ BookingFailure_USER_CANNOT_USE_PAYMENT_OPTION BookingFailure_Cause = 9
+ // A booking that the user tried to cancel has already been cancelled.
+ BookingFailure_BOOKING_ALREADY_CANCELLED BookingFailure_Cause = 10
+ // A booking that the user tried to cancel is not cancellable.
+ BookingFailure_BOOKING_NOT_CANCELLABLE BookingFailure_Cause = 11
+)
+
+var BookingFailure_Cause_name = map[int32]string{
+ 0: "CAUSE_UNSPECIFIED",
+ 1: "SLOT_UNAVAILABLE",
+ 2: "SLOT_ALREADY_BOOKED_BY_USER",
+ 3: "LEASE_EXPIRED",
+ 4: "OUTSIDE_CANCELLATION_WINDOW",
+ 5: "PAYMENT_ERROR_CARD_TYPE_REJECTED",
+ 6: "PAYMENT_ERROR_CARD_DECLINED",
+ 7: "PAYMENT_OPTION_NOT_VALID",
+ 8: "PAYMENT_ERROR",
+ 9: "USER_CANNOT_USE_PAYMENT_OPTION",
+ 10: "BOOKING_ALREADY_CANCELLED",
+ 11: "BOOKING_NOT_CANCELLABLE",
+}
+var BookingFailure_Cause_value = map[string]int32{
+ "CAUSE_UNSPECIFIED": 0,
+ "SLOT_UNAVAILABLE": 1,
+ "SLOT_ALREADY_BOOKED_BY_USER": 2,
+ "LEASE_EXPIRED": 3,
+ "OUTSIDE_CANCELLATION_WINDOW": 4,
+ "PAYMENT_ERROR_CARD_TYPE_REJECTED": 5,
+ "PAYMENT_ERROR_CARD_DECLINED": 6,
+ "PAYMENT_OPTION_NOT_VALID": 7,
+ "PAYMENT_ERROR": 8,
+ "USER_CANNOT_USE_PAYMENT_OPTION": 9,
+ "BOOKING_ALREADY_CANCELLED": 10,
+ "BOOKING_NOT_CANCELLABLE": 11,
+}
+
+func (x BookingFailure_Cause) String() string {
+ return proto.EnumName(BookingFailure_Cause_name, int32(x))
+}
+func (BookingFailure_Cause) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} }
+
+// Set if cause is PAYMENT_ERROR_CARD_TYPE_REJECTED to indicate the type of
+// credit card that was rejected.
+type BookingFailure_CreditCardType int32
+
+const (
+ // Default value. Used if credit card type does not match to one below.
+ BookingFailure_CREDIT_CARD_TYPE_UNSPECIFIED BookingFailure_CreditCardType = 0
+ BookingFailure_VISA BookingFailure_CreditCardType = 1
+ BookingFailure_MASTERCARD BookingFailure_CreditCardType = 2
+ BookingFailure_AMERICAN_EXPRESS BookingFailure_CreditCardType = 3
+ BookingFailure_DISCOVER BookingFailure_CreditCardType = 4
+)
+
+var BookingFailure_CreditCardType_name = map[int32]string{
+ 0: "CREDIT_CARD_TYPE_UNSPECIFIED",
+ 1: "VISA",
+ 2: "MASTERCARD",
+ 3: "AMERICAN_EXPRESS",
+ 4: "DISCOVER",
+}
+var BookingFailure_CreditCardType_value = map[string]int32{
+ "CREDIT_CARD_TYPE_UNSPECIFIED": 0,
+ "VISA": 1,
+ "MASTERCARD": 2,
+ "AMERICAN_EXPRESS": 3,
+ "DISCOVER": 4,
+}
+
+func (x BookingFailure_CreditCardType) String() string {
+ return proto.EnumName(BookingFailure_CreditCardType_name, int32(x))
+}
+func (BookingFailure_CreditCardType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{10, 1}
+}
+
+// This enum indicates what requirements exist for the user to acknowledge or
+// view the requested slots duration/end time.
+type CheckAvailabilityResponse_DurationRequirement int32
+
+const (
+ // The handling of the end time is not specified. This is the default.
+ CheckAvailabilityResponse_DURATION_REQUIREMENT_UNSPECIFIED CheckAvailabilityResponse_DurationRequirement = 0
+ // The end time is not shown to the user.
+ CheckAvailabilityResponse_DO_NOT_SHOW_DURATION CheckAvailabilityResponse_DurationRequirement = 1
+ // The end time has to be shown to the user before an appointment can be
+ // made.
+ CheckAvailabilityResponse_MUST_SHOW_DURATION CheckAvailabilityResponse_DurationRequirement = 2
+)
+
+var CheckAvailabilityResponse_DurationRequirement_name = map[int32]string{
+ 0: "DURATION_REQUIREMENT_UNSPECIFIED",
+ 1: "DO_NOT_SHOW_DURATION",
+ 2: "MUST_SHOW_DURATION",
+}
+var CheckAvailabilityResponse_DurationRequirement_value = map[string]int32{
+ "DURATION_REQUIREMENT_UNSPECIFIED": 0,
+ "DO_NOT_SHOW_DURATION": 1,
+ "MUST_SHOW_DURATION": 2,
+}
+
+func (x CheckAvailabilityResponse_DurationRequirement) String() string {
+ return proto.EnumName(CheckAvailabilityResponse_DurationRequirement_name, int32(x))
+}
+func (CheckAvailabilityResponse_DurationRequirement) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{13, 0}
+}
+
+// An inventory slot
+type Slot struct {
+ // ID of the merchant for the slot
+ MerchantId string `protobuf:"bytes,1,opt,name=merchant_id,json=merchantId" json:"merchant_id,omitempty"`
+ // ID of the merchant service
+ ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId" json:"service_id,omitempty"`
+ // Start time of the appointment slot
+ StartTime *google_protobuf2.Timestamp `protobuf:"bytes,3,opt,name=start_time,json=startTime" json:"start_time,omitempty"`
+ // Duration of the appointment slot
+ Duration *google_protobuf.Duration `protobuf:"bytes,4,opt,name=duration" json:"duration,omitempty"`
+ // Opaque tag that identifies the availability slot and matches the value
+ // provided in the availability feed
+ AvailabilityTag string `protobuf:"bytes,5,opt,name=availability_tag,json=availabilityTag" json:"availability_tag,omitempty"`
+ // The set of resources that disambiguates the appointment slot, e.g. by
+ // indicating the staff member and room selected by the user
+ Resources *Resources `protobuf:"bytes,6,opt,name=resources" json:"resources,omitempty"`
+}
+
+func (m *Slot) Reset() { *m = Slot{} }
+func (m *Slot) String() string { return proto.CompactTextString(m) }
+func (*Slot) ProtoMessage() {}
+func (*Slot) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *Slot) GetMerchantId() string {
+ if m != nil {
+ return m.MerchantId
+ }
+ return ""
+}
+
+func (m *Slot) GetServiceId() string {
+ if m != nil {
+ return m.ServiceId
+ }
+ return ""
+}
+
+func (m *Slot) GetStartTime() *google_protobuf2.Timestamp {
+ if m != nil {
+ return m.StartTime
+ }
+ return nil
+}
+
+func (m *Slot) GetDuration() *google_protobuf.Duration {
+ if m != nil {
+ return m.Duration
+ }
+ return nil
+}
+
+func (m *Slot) GetAvailabilityTag() string {
+ if m != nil {
+ return m.AvailabilityTag
+ }
+ return ""
+}
+
+func (m *Slot) GetResources() *Resources {
+ if m != nil {
+ return m.Resources
+ }
+ return nil
+}
+
+// Temporary lease for an inventory slot
+type Lease struct {
+ // ID of the lease.
+ // Not populated in CreateLeaseRequest. The value is chosen by the partner and
+ // has to be returned in the response of CreateLease.
+ LeaseId string `protobuf:"bytes,1,opt,name=lease_id,json=leaseId" json:"lease_id,omitempty"`
+ // The appointment slot that the lease is created for.
+ Slot *Slot `protobuf:"bytes,2,opt,name=slot" json:"slot,omitempty"`
+ // Unique identifier for this lease, chosen by Reserve with Google. Serves as
+ // an idempotency token for [ext.maps.booking.partner.v2.CreateLease]
+ // requests.
+ UserReference string `protobuf:"bytes,3,opt,name=user_reference,json=userReference" json:"user_reference,omitempty"`
+ // Expiration time of the lease
+ LeaseExpirationTime *google_protobuf2.Timestamp `protobuf:"bytes,4,opt,name=lease_expiration_time,json=leaseExpirationTime" json:"lease_expiration_time,omitempty"`
+}
+
+func (m *Lease) Reset() { *m = Lease{} }
+func (m *Lease) String() string { return proto.CompactTextString(m) }
+func (*Lease) ProtoMessage() {}
+func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *Lease) GetLeaseId() string {
+ if m != nil {
+ return m.LeaseId
+ }
+ return ""
+}
+
+func (m *Lease) GetSlot() *Slot {
+ if m != nil {
+ return m.Slot
+ }
+ return nil
+}
+
+func (m *Lease) GetUserReference() string {
+ if m != nil {
+ return m.UserReference
+ }
+ return ""
+}
+
+func (m *Lease) GetLeaseExpirationTime() *google_protobuf2.Timestamp {
+ if m != nil {
+ return m.LeaseExpirationTime
+ }
+ return nil
+}
+
+// Reference to a [ext.maps.booking.partner.v2.Lease] that has been created via
+// [ext.maps.booking.partner.v2.CreateLease]
+type LeaseReference struct {
+ // Lease ID
+ LeaseId string `protobuf:"bytes,1,opt,name=lease_id,json=leaseId" json:"lease_id,omitempty"`
+}
+
+func (m *LeaseReference) Reset() { *m = LeaseReference{} }
+func (m *LeaseReference) String() string { return proto.CompactTextString(m) }
+func (*LeaseReference) ProtoMessage() {}
+func (*LeaseReference) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *LeaseReference) GetLeaseId() string {
+ if m != nil {
+ return m.LeaseId
+ }
+ return ""
+}
+
+// A booking for an inventory slot
+type Booking struct {
+ // ID of this booking
+ BookingId string `protobuf:"bytes,1,opt,name=booking_id,json=bookingId" json:"booking_id,omitempty"`
+ // The appointment slot of this booking
+ Slot *Slot `protobuf:"bytes,2,opt,name=slot" json:"slot,omitempty"`
+ // Personal information of the user making the appointment
+ UserInformation *UserInformation `protobuf:"bytes,3,opt,name=user_information,json=userInformation" json:"user_information,omitempty"`
+ // Status of the booking
+ Status BookingStatus `protobuf:"varint,4,opt,name=status,enum=ext.maps.booking.partner.v2.BookingStatus" json:"status,omitempty"`
+ // Information about payment transactions that relate to the booking.
+ PaymentInformation *PaymentInformation `protobuf:"bytes,5,opt,name=payment_information,json=paymentInformation" json:"payment_information,omitempty"`
+}
+
+func (m *Booking) Reset() { *m = Booking{} }
+func (m *Booking) String() string { return proto.CompactTextString(m) }
+func (*Booking) ProtoMessage() {}
+func (*Booking) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *Booking) GetBookingId() string {
+ if m != nil {
+ return m.BookingId
+ }
+ return ""
+}
+
+func (m *Booking) GetSlot() *Slot {
+ if m != nil {
+ return m.Slot
+ }
+ return nil
+}
+
+func (m *Booking) GetUserInformation() *UserInformation {
+ if m != nil {
+ return m.UserInformation
+ }
+ return nil
+}
+
+func (m *Booking) GetStatus() BookingStatus {
+ if m != nil {
+ return m.Status
+ }
+ return BookingStatus_BOOKING_STATUS_UNSPECIFIED
+}
+
+func (m *Booking) GetPaymentInformation() *PaymentInformation {
+ if m != nil {
+ return m.PaymentInformation
+ }
+ return nil
+}
+
+// Personal information about the person making a booking
+type UserInformation struct {
+ // Unique ID of the user to the partner, chosen by Reserve with Google.
+ UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId" json:"user_id,omitempty"`
+ // Given name of the user
+ GivenName string `protobuf:"bytes,2,opt,name=given_name,json=givenName" json:"given_name,omitempty"`
+ // Family name of the user
+ FamilyName string `protobuf:"bytes,3,opt,name=family_name,json=familyName" json:"family_name,omitempty"`
+ // Address of the user (optional)
+ Address *PostalAddress `protobuf:"bytes,4,opt,name=address" json:"address,omitempty"`
+ // Phone number of the user (optional)
+ Telephone string `protobuf:"bytes,5,opt,name=telephone" json:"telephone,omitempty"`
+ // Email address of the user
+ Email string `protobuf:"bytes,6,opt,name=email" json:"email,omitempty"`
+}
+
+func (m *UserInformation) Reset() { *m = UserInformation{} }
+func (m *UserInformation) String() string { return proto.CompactTextString(m) }
+func (*UserInformation) ProtoMessage() {}
+func (*UserInformation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *UserInformation) GetUserId() string {
+ if m != nil {
+ return m.UserId
+ }
+ return ""
+}
+
+func (m *UserInformation) GetGivenName() string {
+ if m != nil {
+ return m.GivenName
+ }
+ return ""
+}
+
+func (m *UserInformation) GetFamilyName() string {
+ if m != nil {
+ return m.FamilyName
+ }
+ return ""
+}
+
+func (m *UserInformation) GetAddress() *PostalAddress {
+ if m != nil {
+ return m.Address
+ }
+ return nil
+}
+
+func (m *UserInformation) GetTelephone() string {
+ if m != nil {
+ return m.Telephone
+ }
+ return ""
+}
+
+func (m *UserInformation) GetEmail() string {
+ if m != nil {
+ return m.Email
+ }
+ return ""
+}
+
+// Postal address for a user
+type PostalAddress struct {
+ // The country, e.g. "USA".
+ AddressCountry string `protobuf:"bytes,1,opt,name=address_country,json=addressCountry" json:"address_country,omitempty"`
+ // The locality, e.g. "Mountain View".
+ AddressLocality string `protobuf:"bytes,2,opt,name=address_locality,json=addressLocality" json:"address_locality,omitempty"`
+ // The region, e.g. "CA".
+ AddressRegion string `protobuf:"bytes,3,opt,name=address_region,json=addressRegion" json:"address_region,omitempty"`
+ // The post office box number, e.g. "3112", optional.
+ PostOfficeBoxNumber string `protobuf:"bytes,4,opt,name=post_office_box_number,json=postOfficeBoxNumber" json:"post_office_box_number,omitempty"`
+ // The postal code, e.g. "94043".
+ PostalCode string `protobuf:"bytes,5,opt,name=postal_code,json=postalCode" json:"postal_code,omitempty"`
+ // The street address, e.g. "1600 Amphitheatre Pkwy".
+ StreetAddress string `protobuf:"bytes,6,opt,name=street_address,json=streetAddress" json:"street_address,omitempty"`
+}
+
+func (m *PostalAddress) Reset() { *m = PostalAddress{} }
+func (m *PostalAddress) String() string { return proto.CompactTextString(m) }
+func (*PostalAddress) ProtoMessage() {}
+func (*PostalAddress) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *PostalAddress) GetAddressCountry() string {
+ if m != nil {
+ return m.AddressCountry
+ }
+ return ""
+}
+
+func (m *PostalAddress) GetAddressLocality() string {
+ if m != nil {
+ return m.AddressLocality
+ }
+ return ""
+}
+
+func (m *PostalAddress) GetAddressRegion() string {
+ if m != nil {
+ return m.AddressRegion
+ }
+ return ""
+}
+
+func (m *PostalAddress) GetPostOfficeBoxNumber() string {
+ if m != nil {
+ return m.PostOfficeBoxNumber
+ }
+ return ""
+}
+
+func (m *PostalAddress) GetPostalCode() string {
+ if m != nil {
+ return m.PostalCode
+ }
+ return ""
+}
+
+func (m *PostalAddress) GetStreetAddress() string {
+ if m != nil {
+ return m.StreetAddress
+ }
+ return ""
+}
+
+// Parameters to specify how the partner will process payment for a given
+// booking.
+//
+// A sample request:
+// processor: PROCESSOR_STRIPE
+// payment_method_token: "pk_live_12345abcdef"
+// version: "2017-06-15"
+type PaymentProcessingParameters struct {
+ Processor PaymentProcessingParameters_PaymentProcessor `protobuf:"varint,1,opt,name=processor,enum=ext.maps.booking.partner.v2.PaymentProcessingParameters_PaymentProcessor" json:"processor,omitempty"`
+ // The token representing the payment method that will be used to pay
+ // for this booking. This token can be only used once. This token can be
+ // only used for the merchant associated with this booking.
+ //
+ // Each processor may choose its own format for this field.
+ // Stripe uses "pk_live_1234abc..." for live keys and "pk_test_1234abc..."
+ // for test keys.
+ PaymentMethodToken string `protobuf:"bytes,2,opt,name=payment_method_token,json=paymentMethodToken" json:"payment_method_token,omitempty"`
+ // The payment processor API version that the given payment token is valid
+ // for.
+ //
+ // Each processor may choose its own format for this field.
+ // Stripe uses a date (e.g. "2017-06-15").
+ Version string `protobuf:"bytes,3,opt,name=version" json:"version,omitempty"`
+}
+
+func (m *PaymentProcessingParameters) Reset() { *m = PaymentProcessingParameters{} }
+func (m *PaymentProcessingParameters) String() string { return proto.CompactTextString(m) }
+func (*PaymentProcessingParameters) ProtoMessage() {}
+func (*PaymentProcessingParameters) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+func (m *PaymentProcessingParameters) GetProcessor() PaymentProcessingParameters_PaymentProcessor {
+ if m != nil {
+ return m.Processor
+ }
+ return PaymentProcessingParameters_PAYMENT_PROCESSOR_UNSPECIFIED
+}
+
+func (m *PaymentProcessingParameters) GetPaymentMethodToken() string {
+ if m != nil {
+ return m.PaymentMethodToken
+ }
+ return ""
+}
+
+func (m *PaymentProcessingParameters) GetVersion() string {
+ if m != nil {
+ return m.Version
+ }
+ return ""
+}
+
+type Price struct {
+ // The price in micro-units of the currency.
+ // Fractions of smallest currency unit will be rounded using nearest even
+ // rounding. (e.g. For USD 2.5 cents rounded to 2 cents, 3.5 cents rounded to
+ // 4 cents, 0.5 cents rounded to 0 cents, 2.51 cents rounded to 3 cents).
+ PriceMicros int64 `protobuf:"varint,1,opt,name=price_micros,json=priceMicros" json:"price_micros,omitempty"`
+ // The currency of the price that is defined in ISO 4217.
+ CurrencyCode string `protobuf:"bytes,2,opt,name=currency_code,json=currencyCode" json:"currency_code,omitempty"`
+}
+
+func (m *Price) Reset() { *m = Price{} }
+func (m *Price) String() string { return proto.CompactTextString(m) }
+func (*Price) ProtoMessage() {}
+func (*Price) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+func (m *Price) GetPriceMicros() int64 {
+ if m != nil {
+ return m.PriceMicros
+ }
+ return 0
+}
+
+func (m *Price) GetCurrencyCode() string {
+ if m != nil {
+ return m.CurrencyCode
+ }
+ return ""
+}
+
+// This describes a payment option, such as a pack, membership, or
+// single-session pass after it has been purchased by a user. It includes an
+// identifier for the user payment option, as well as some information about
+// the payment option with which it is associated.
+type UserPaymentOption struct {
+ // A unique identifier for the user payment option. This Id MUST be unique
+ // for all UserPaymentOptions across all merchants and users.
+ UserPaymentOptionId string `protobuf:"bytes,1,opt,name=user_payment_option_id,json=userPaymentOptionId" json:"user_payment_option_id,omitempty"`
+ // The user payment option will be valid (usable) between start_time and
+ // end_time. Attempts to use a user payment option to make a booking outside
+ // of this interval will fail.
+ ValidStartTime *google_protobuf2.Timestamp `protobuf:"bytes,2,opt,name=valid_start_time,json=validStartTime" json:"valid_start_time,omitempty"`
+ ValidEndTime *google_protobuf2.Timestamp `protobuf:"bytes,3,opt,name=valid_end_time,json=validEndTime" json:"valid_end_time,omitempty"`
+ // The type of the payment option associated with this user payment option.
+ // This can be unlimited for a membership or subscription, multi-use for a
+ // pack, or single-use.
+ Type PaymentOptionType `protobuf:"varint,4,opt,name=type,enum=ext.maps.booking.partner.v2.PaymentOptionType" json:"type,omitempty"`
+ // The original number of uses for this user payment option when it was
+ // purchased. This value is ignored for unlimited payment options.
+ OriginalCount int32 `protobuf:"varint,5,opt,name=original_count,json=originalCount" json:"original_count,omitempty"`
+ // The number of uses remaining for this user payment option. If this number
+ // is 0 for a pack, attempts to use this payment option to make a booking will
+ // fail.
+ CurrentCount int32 `protobuf:"varint,6,opt,name=current_count,json=currentCount" json:"current_count,omitempty"`
+ // The id of the payment option that has been used to purchase this user
+ // payment option.
+ PaymentOptionId string `protobuf:"bytes,7,opt,name=payment_option_id,json=paymentOptionId" json:"payment_option_id,omitempty"`
+}
+
+func (m *UserPaymentOption) Reset() { *m = UserPaymentOption{} }
+func (m *UserPaymentOption) String() string { return proto.CompactTextString(m) }
+func (*UserPaymentOption) ProtoMessage() {}
+func (*UserPaymentOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+
+func (m *UserPaymentOption) GetUserPaymentOptionId() string {
+ if m != nil {
+ return m.UserPaymentOptionId
+ }
+ return ""
+}
+
+func (m *UserPaymentOption) GetValidStartTime() *google_protobuf2.Timestamp {
+ if m != nil {
+ return m.ValidStartTime
+ }
+ return nil
+}
+
+func (m *UserPaymentOption) GetValidEndTime() *google_protobuf2.Timestamp {
+ if m != nil {
+ return m.ValidEndTime
+ }
+ return nil
+}
+
+func (m *UserPaymentOption) GetType() PaymentOptionType {
+ if m != nil {
+ return m.Type
+ }
+ return PaymentOptionType_PAYMENT_OPTION_TYPE_UNSPECIFIED
+}
+
+func (m *UserPaymentOption) GetOriginalCount() int32 {
+ if m != nil {
+ return m.OriginalCount
+ }
+ return 0
+}
+
+func (m *UserPaymentOption) GetCurrentCount() int32 {
+ if m != nil {
+ return m.CurrentCount
+ }
+ return 0
+}
+
+func (m *UserPaymentOption) GetPaymentOptionId() string {
+ if m != nil {
+ return m.PaymentOptionId
+ }
+ return ""
+}
+
+// Payment details that are sent when creating a new booking.
+type PaymentInformation struct {
+ // Prepayment status of the booking.
+ // If the prepayment_status is PREPAYMENT_PROVIDED, then
+ // payment_transaction_id contains the associated unique transaction id for
+ // the purchase.
+ // If the prepayment status is PREPAYMENT_REFUNDED, then
+ // payment_transaction_id contains the associated unique transaction id for
+ // the refund.
+ PrepaymentStatus PrepaymentStatus `protobuf:"varint,1,opt,name=prepayment_status,json=prepaymentStatus,enum=ext.maps.booking.partner.v2.PrepaymentStatus" json:"prepayment_status,omitempty"`
+ // Unique identifier for a payment transaction associated with the booking.
+ // Empty if not applicable.
+ PaymentTransactionId string `protobuf:"bytes,2,opt,name=payment_transaction_id,json=paymentTransactionId" json:"payment_transaction_id,omitempty"`
+ // These fields must match the service price (specified in the Services feed)
+ // or the PaymentOption corresponding with this service.
+ // They are included in the booking request and response to verify that
+ // the price indicated in the feed has not changed since the last feed
+ // update.
+ //
+ // The price of the booking, exclusive of any taxes.
+ // Existence of price or taxes does not imply that they have been paid,
+ // prepayment_state should be used for that purpose.
+ Price *Price `protobuf:"bytes,3,opt,name=price" json:"price,omitempty"`
+ // Taxes that are calculated to be paid for this booking.
+ // If this field is absent the price is assumed to be exempt from or already
+ // inclusive of applicable taxes.
+ TaxAmount *Price `protobuf:"bytes,4,opt,name=tax_amount,json=taxAmount" json:"tax_amount,omitempty"`
+ PaymentProcessedBy PaymentInformation_PaymentProcessedBy `protobuf:"varint,5,opt,name=payment_processed_by,json=paymentProcessedBy,enum=ext.maps.booking.partner.v2.PaymentInformation_PaymentProcessedBy" json:"payment_processed_by,omitempty"`
+ // The id of the payment option or user payment option associated with the
+ // booking.
+ // If a payment option is purchased as part of a booking, payment_option_id
+ // will be set with the id of that payment option.
+ // If an already purchased user payment option is being used to pay for a
+ // booking, user_payment_option_id will be set with the id of that user
+ // payment option.
+ // When included as part of a response proto, the user_payment_option_id
+ // should be set and must match the UserPaymentOption that is returned in the
+ // RPC response (e.g. the user_payment_option returned in
+ // CreateBookingResponse).
+ //
+ // Types that are valid to be assigned to PaymentId:
+ // *PaymentInformation_PaymentOptionId
+ // *PaymentInformation_UserPaymentOptionId
+ PaymentId isPaymentInformation_PaymentId `protobuf_oneof:"payment_id"`
+}
+
+func (m *PaymentInformation) Reset() { *m = PaymentInformation{} }
+func (m *PaymentInformation) String() string { return proto.CompactTextString(m) }
+func (*PaymentInformation) ProtoMessage() {}
+func (*PaymentInformation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+
+type isPaymentInformation_PaymentId interface {
+ isPaymentInformation_PaymentId()
+}
+
+type PaymentInformation_PaymentOptionId struct {
+ PaymentOptionId string `protobuf:"bytes,6,opt,name=payment_option_id,json=paymentOptionId,oneof"`
+}
+type PaymentInformation_UserPaymentOptionId struct {
+ UserPaymentOptionId string `protobuf:"bytes,7,opt,name=user_payment_option_id,json=userPaymentOptionId,oneof"`
+}
+
+func (*PaymentInformation_PaymentOptionId) isPaymentInformation_PaymentId() {}
+func (*PaymentInformation_UserPaymentOptionId) isPaymentInformation_PaymentId() {}
+
+func (m *PaymentInformation) GetPaymentId() isPaymentInformation_PaymentId {
+ if m != nil {
+ return m.PaymentId
+ }
+ return nil
+}
+
+func (m *PaymentInformation) GetPrepaymentStatus() PrepaymentStatus {
+ if m != nil {
+ return m.PrepaymentStatus
+ }
+ return PrepaymentStatus_PREPAYMENT_STATUS_UNSPECIFIED
+}
+
+func (m *PaymentInformation) GetPaymentTransactionId() string {
+ if m != nil {
+ return m.PaymentTransactionId
+ }
+ return ""
+}
+
+func (m *PaymentInformation) GetPrice() *Price {
+ if m != nil {
+ return m.Price
+ }
+ return nil
+}
+
+func (m *PaymentInformation) GetTaxAmount() *Price {
+ if m != nil {
+ return m.TaxAmount
+ }
+ return nil
+}
+
+func (m *PaymentInformation) GetPaymentProcessedBy() PaymentInformation_PaymentProcessedBy {
+ if m != nil {
+ return m.PaymentProcessedBy
+ }
+ return PaymentInformation_PAYMENT_PROCESSED_BY_UNSPECIFIED
+}
+
+func (m *PaymentInformation) GetPaymentOptionId() string {
+ if x, ok := m.GetPaymentId().(*PaymentInformation_PaymentOptionId); ok {
+ return x.PaymentOptionId
+ }
+ return ""
+}
+
+func (m *PaymentInformation) GetUserPaymentOptionId() string {
+ if x, ok := m.GetPaymentId().(*PaymentInformation_UserPaymentOptionId); ok {
+ return x.UserPaymentOptionId
+ }
+ return ""
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*PaymentInformation) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _PaymentInformation_OneofMarshaler, _PaymentInformation_OneofUnmarshaler, _PaymentInformation_OneofSizer, []interface{}{
+ (*PaymentInformation_PaymentOptionId)(nil),
+ (*PaymentInformation_UserPaymentOptionId)(nil),
+ }
+}
+
+func _PaymentInformation_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*PaymentInformation)
+ // payment_id
+ switch x := m.PaymentId.(type) {
+ case *PaymentInformation_PaymentOptionId:
+ b.EncodeVarint(6<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.PaymentOptionId)
+ case *PaymentInformation_UserPaymentOptionId:
+ b.EncodeVarint(7<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.UserPaymentOptionId)
+ case nil:
+ default:
+ return fmt.Errorf("PaymentInformation.PaymentId has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _PaymentInformation_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*PaymentInformation)
+ switch tag {
+ case 6: // payment_id.payment_option_id
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.PaymentId = &PaymentInformation_PaymentOptionId{x}
+ return true, err
+ case 7: // payment_id.user_payment_option_id
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.PaymentId = &PaymentInformation_UserPaymentOptionId{x}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _PaymentInformation_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*PaymentInformation)
+ // payment_id
+ switch x := m.PaymentId.(type) {
+ case *PaymentInformation_PaymentOptionId:
+ n += proto.SizeVarint(6<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.PaymentOptionId)))
+ n += len(x.PaymentOptionId)
+ case *PaymentInformation_UserPaymentOptionId:
+ n += proto.SizeVarint(7<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.UserPaymentOptionId)))
+ n += len(x.UserPaymentOptionId)
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+// Status data that conveys why (1) creating a lease or (2) creating or updating
+// a booking fails.
+// BookingFailure is intended to primarily capture business logic errors.
+type BookingFailure struct {
+ Cause BookingFailure_Cause `protobuf:"varint,1,opt,name=cause,enum=ext.maps.booking.partner.v2.BookingFailure_Cause" json:"cause,omitempty"`
+ RejectedCardType BookingFailure_CreditCardType `protobuf:"varint,2,opt,name=rejected_card_type,json=rejectedCardType,enum=ext.maps.booking.partner.v2.BookingFailure_CreditCardType" json:"rejected_card_type,omitempty"`
+ // This optional field is used for the partner to include additional
+ // information for debugging purpose only.
+ Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
+}
+
+func (m *BookingFailure) Reset() { *m = BookingFailure{} }
+func (m *BookingFailure) String() string { return proto.CompactTextString(m) }
+func (*BookingFailure) ProtoMessage() {}
+func (*BookingFailure) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+
+func (m *BookingFailure) GetCause() BookingFailure_Cause {
+ if m != nil {
+ return m.Cause
+ }
+ return BookingFailure_CAUSE_UNSPECIFIED
+}
+
+func (m *BookingFailure) GetRejectedCardType() BookingFailure_CreditCardType {
+ if m != nil {
+ return m.RejectedCardType
+ }
+ return BookingFailure_CREDIT_CARD_TYPE_UNSPECIFIED
+}
+
+func (m *BookingFailure) GetDescription() string {
+ if m != nil {
+ return m.Description
+ }
+ return ""
+}
+
+// Resource specification that disambiguates an appointment slot
+type Resources struct {
+ // The staff ID as provided in the feed or empty if not applicable or no staff
+ // was selected.
+ StaffId string `protobuf:"bytes,1,opt,name=staff_id,json=staffId" json:"staff_id,omitempty"`
+ // The room ID as provided in the feed or empty if not applicable or no room
+ // was selected.
+ RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId" json:"room_id,omitempty"`
+ // For Dining Reservations only: the number of seats requested in the booking.
+ PartySize int32 `protobuf:"varint,3,opt,name=party_size,json=partySize" json:"party_size,omitempty"`
+}
+
+func (m *Resources) Reset() { *m = Resources{} }
+func (m *Resources) String() string { return proto.CompactTextString(m) }
+func (*Resources) ProtoMessage() {}
+func (*Resources) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+
+func (m *Resources) GetStaffId() string {
+ if m != nil {
+ return m.StaffId
+ }
+ return ""
+}
+
+func (m *Resources) GetRoomId() string {
+ if m != nil {
+ return m.RoomId
+ }
+ return ""
+}
+
+func (m *Resources) GetPartySize() int32 {
+ if m != nil {
+ return m.PartySize
+ }
+ return 0
+}
+
+// Request to check availability for a [ext.maps.booking.partner.v2.Slot]
+type CheckAvailabilityRequest struct {
+ // The appointment slot that is being checked
+ Slot *Slot `protobuf:"bytes,1,opt,name=slot" json:"slot,omitempty"`
+}
+
+func (m *CheckAvailabilityRequest) Reset() { *m = CheckAvailabilityRequest{} }
+func (m *CheckAvailabilityRequest) String() string { return proto.CompactTextString(m) }
+func (*CheckAvailabilityRequest) ProtoMessage() {}
+func (*CheckAvailabilityRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+
+func (m *CheckAvailabilityRequest) GetSlot() *Slot {
+ if m != nil {
+ return m.Slot
+ }
+ return nil
+}
+
+// Response for the [ext.maps.booking.partner.v2.CheckAvailability] RPC with the
+// availability of the appointment slot
+type CheckAvailabilityResponse struct {
+ // The requested slot.
+ Slot *Slot `protobuf:"bytes,1,opt,name=slot" json:"slot,omitempty"`
+ // Number of available spots.
+ // 0 indicates that the appointment slot is not available.
+ CountAvailable int32 `protobuf:"varint,2,opt,name=count_available,json=countAvailable" json:"count_available,omitempty"`
+ // Optionally, return the requirement to show the slots duration and/or
+ // endtime. This field will be ignored if slot is unavailable.
+ DurationRequirement CheckAvailabilityResponse_DurationRequirement `protobuf:"varint,3,opt,name=duration_requirement,json=durationRequirement,enum=ext.maps.booking.partner.v2.CheckAvailabilityResponse_DurationRequirement" json:"duration_requirement,omitempty"`
+}
+
+func (m *CheckAvailabilityResponse) Reset() { *m = CheckAvailabilityResponse{} }
+func (m *CheckAvailabilityResponse) String() string { return proto.CompactTextString(m) }
+func (*CheckAvailabilityResponse) ProtoMessage() {}
+func (*CheckAvailabilityResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+
+func (m *CheckAvailabilityResponse) GetSlot() *Slot {
+ if m != nil {
+ return m.Slot
+ }
+ return nil
+}
+
+func (m *CheckAvailabilityResponse) GetCountAvailable() int32 {
+ if m != nil {
+ return m.CountAvailable
+ }
+ return 0
+}
+
+func (m *CheckAvailabilityResponse) GetDurationRequirement() CheckAvailabilityResponse_DurationRequirement {
+ if m != nil {
+ return m.DurationRequirement
+ }
+ return CheckAvailabilityResponse_DURATION_REQUIREMENT_UNSPECIFIED
+}
+
+// Request to create a [ext.maps.booking.partner.v2.Lease] for a slot in the
+// inventory. The expiration time in the returned Lease may be modified by the
+// backend, e.g. if the requested lease period is too long.
+type CreateLeaseRequest struct {
+ // The lease to be created with information about the appointment slot
+ Lease *Lease `protobuf:"bytes,1,opt,name=lease" json:"lease,omitempty"`
+}
+
+func (m *CreateLeaseRequest) Reset() { *m = CreateLeaseRequest{} }
+func (m *CreateLeaseRequest) String() string { return proto.CompactTextString(m) }
+func (*CreateLeaseRequest) ProtoMessage() {}
+func (*CreateLeaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+
+func (m *CreateLeaseRequest) GetLease() *Lease {
+ if m != nil {
+ return m.Lease
+ }
+ return nil
+}
+
+// Response for the [ext.maps.booking.partner.v2.CreateLease] RPC with the
+// created [ext.maps.booking.partner.v2.Lease]
+type CreateLeaseResponse struct {
+ // The created [ext.maps.booking.partner.v2.Lease]
+ Lease *Lease `protobuf:"bytes,1,opt,name=lease" json:"lease,omitempty"`
+ // If creating a lease fails, this field should reflect the business logic
+ // error (e.g., slot has become unavailable) and lease field is expected to be
+ // unset.
+ BookingFailure *BookingFailure `protobuf:"bytes,2,opt,name=booking_failure,json=bookingFailure" json:"booking_failure,omitempty"`
+}
+
+func (m *CreateLeaseResponse) Reset() { *m = CreateLeaseResponse{} }
+func (m *CreateLeaseResponse) String() string { return proto.CompactTextString(m) }
+func (*CreateLeaseResponse) ProtoMessage() {}
+func (*CreateLeaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+
+func (m *CreateLeaseResponse) GetLease() *Lease {
+ if m != nil {
+ return m.Lease
+ }
+ return nil
+}
+
+func (m *CreateLeaseResponse) GetBookingFailure() *BookingFailure {
+ if m != nil {
+ return m.BookingFailure
+ }
+ return nil
+}
+
+// Request to create a [ext.maps.booking.partner.v2.Booking] for an inventory
+// slot. Consumes the lease if provided.
+type CreateBookingRequest struct {
+ // The inventory slot that is being requested to make this booking.
+ // If lease_ref is provided, slot must match the lease; slot is provided for
+ // the partner to verify the lease information.
+ // If lease_ref is absent, then create the booking for the slot.
+ Slot *Slot `protobuf:"bytes,1,opt,name=slot" json:"slot,omitempty"`
+ // The lease that is being confirmed to make this booking.
+ // If lease_ref is provided, then create the booking using the lease.
+ LeaseRef *LeaseReference `protobuf:"bytes,2,opt,name=lease_ref,json=leaseRef" json:"lease_ref,omitempty"`
+ // Personal information of the user making the appointment
+ UserInformation *UserInformation `protobuf:"bytes,3,opt,name=user_information,json=userInformation" json:"user_information,omitempty"`
+ // Information about payments. When payment authorizations are handled by
+ // Google, if the booking request does not succeed, payment authorizations are
+ // automatically canceled.
+ PaymentInformation *PaymentInformation `protobuf:"bytes,4,opt,name=payment_information,json=paymentInformation" json:"payment_information,omitempty"`
+ // The parameters to be used if the payment is processed by the partner
+ // (i.e. payment_information.payment_processed_by is equal to
+ // PROCESSED_BY_PARTNER).
+ PaymentProcessingParameters *PaymentProcessingParameters `protobuf:"bytes,5,opt,name=payment_processing_parameters,json=paymentProcessingParameters" json:"payment_processing_parameters,omitempty"`
+ // Idempotency token for [ext.maps.booking.partner.v2.CreateBooking] requests.
+ IdempotencyToken string `protobuf:"bytes,6,opt,name=idempotency_token,json=idempotencyToken" json:"idempotency_token,omitempty"`
+}
+
+func (m *CreateBookingRequest) Reset() { *m = CreateBookingRequest{} }
+func (m *CreateBookingRequest) String() string { return proto.CompactTextString(m) }
+func (*CreateBookingRequest) ProtoMessage() {}
+func (*CreateBookingRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+
+func (m *CreateBookingRequest) GetSlot() *Slot {
+ if m != nil {
+ return m.Slot
+ }
+ return nil
+}
+
+func (m *CreateBookingRequest) GetLeaseRef() *LeaseReference {
+ if m != nil {
+ return m.LeaseRef
+ }
+ return nil
+}
+
+func (m *CreateBookingRequest) GetUserInformation() *UserInformation {
+ if m != nil {
+ return m.UserInformation
+ }
+ return nil
+}
+
+func (m *CreateBookingRequest) GetPaymentInformation() *PaymentInformation {
+ if m != nil {
+ return m.PaymentInformation
+ }
+ return nil
+}
+
+func (m *CreateBookingRequest) GetPaymentProcessingParameters() *PaymentProcessingParameters {
+ if m != nil {
+ return m.PaymentProcessingParameters
+ }
+ return nil
+}
+
+func (m *CreateBookingRequest) GetIdempotencyToken() string {
+ if m != nil {
+ return m.IdempotencyToken
+ }
+ return ""
+}
+
+// Response with the created [ext.maps.booking.partner.v2.Booking] for an
+// inventory slot
+type CreateBookingResponse struct {
+ // The created booking
+ Booking *Booking `protobuf:"bytes,1,opt,name=booking" json:"booking,omitempty"`
+ // The updated user payment option used in this booking.
+ // If a new payment option was purchased to pay for the booking, this should
+ // be a newly created user payment option.
+ // If an already purchased user payment option was used for this booking,
+ // this should reflect an updated version of that user payment option.
+ UserPaymentOption *UserPaymentOption `protobuf:"bytes,2,opt,name=user_payment_option,json=userPaymentOption" json:"user_payment_option,omitempty"`
+ // If creating a booking fails, this field should reflect the business logic
+ // error (e.g., slot has become unavailable) and all other fields in the
+ // CreateBookingResponse message are expected to be unset.
+ BookingFailure *BookingFailure `protobuf:"bytes,3,opt,name=booking_failure,json=bookingFailure" json:"booking_failure,omitempty"`
+}
+
+func (m *CreateBookingResponse) Reset() { *m = CreateBookingResponse{} }
+func (m *CreateBookingResponse) String() string { return proto.CompactTextString(m) }
+func (*CreateBookingResponse) ProtoMessage() {}
+func (*CreateBookingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
+
+func (m *CreateBookingResponse) GetBooking() *Booking {
+ if m != nil {
+ return m.Booking
+ }
+ return nil
+}
+
+func (m *CreateBookingResponse) GetUserPaymentOption() *UserPaymentOption {
+ if m != nil {
+ return m.UserPaymentOption
+ }
+ return nil
+}
+
+func (m *CreateBookingResponse) GetBookingFailure() *BookingFailure {
+ if m != nil {
+ return m.BookingFailure
+ }
+ return nil
+}
+
+// Request to update a [ext.maps.booking.partner.v2.Booking]
+type UpdateBookingRequest struct {
+ // Field mask of all booking fields to be updated
+ UpdateMask *google_protobuf1.FieldMask `protobuf:"bytes,1,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"`
+ // The booking to be updated
+ // The following fields can be set in a booking:
+ // - status, to cancel a booking.
+ // - start_time and duration in the slot, to reschedule a booking.
+ Booking *Booking `protobuf:"bytes,2,opt,name=booking" json:"booking,omitempty"`
+}
+
+func (m *UpdateBookingRequest) Reset() { *m = UpdateBookingRequest{} }
+func (m *UpdateBookingRequest) String() string { return proto.CompactTextString(m) }
+func (*UpdateBookingRequest) ProtoMessage() {}
+func (*UpdateBookingRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+
+func (m *UpdateBookingRequest) GetUpdateMask() *google_protobuf1.FieldMask {
+ if m != nil {
+ return m.UpdateMask
+ }
+ return nil
+}
+
+func (m *UpdateBookingRequest) GetBooking() *Booking {
+ if m != nil {
+ return m.Booking
+ }
+ return nil
+}
+
+// Response with the updated [ext.maps.booking.partner.v2.Booking]
+type UpdateBookingResponse struct {
+ // The updated booking
+ Booking *Booking `protobuf:"bytes,1,opt,name=booking" json:"booking,omitempty"`
+ // The updated user payment option originally used to pay for this booking.
+ // This should be set if the UpdateBookingRequest results in a change to
+ // the UserPaymentOption.
+ // For instance, if the booking is canceled, the UserPaymentOption should
+ // reflect an additional credit to the user. In the case of a multi-use
+ // payment option, the current_count should be increased by one to
+ // allow the user to create another booking with this payment option. In the
+ // case of a single-use payment option, a new single-use user payment option
+ // should be returned.
+ UserPaymentOption *UserPaymentOption `protobuf:"bytes,2,opt,name=user_payment_option,json=userPaymentOption" json:"user_payment_option,omitempty"`
+ // If updating a booking fails, this field should reflect the business logic
+ // error (e.g., booking is not cancellable)
+ BookingFailure *BookingFailure `protobuf:"bytes,3,opt,name=booking_failure,json=bookingFailure" json:"booking_failure,omitempty"`
+}
+
+func (m *UpdateBookingResponse) Reset() { *m = UpdateBookingResponse{} }
+func (m *UpdateBookingResponse) String() string { return proto.CompactTextString(m) }
+func (*UpdateBookingResponse) ProtoMessage() {}
+func (*UpdateBookingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
+
+func (m *UpdateBookingResponse) GetBooking() *Booking {
+ if m != nil {
+ return m.Booking
+ }
+ return nil
+}
+
+func (m *UpdateBookingResponse) GetUserPaymentOption() *UserPaymentOption {
+ if m != nil {
+ return m.UserPaymentOption
+ }
+ return nil
+}
+
+func (m *UpdateBookingResponse) GetBookingFailure() *BookingFailure {
+ if m != nil {
+ return m.BookingFailure
+ }
+ return nil
+}
+
+// Request to get booking status and prepayment status for a
+// [ext.maps.booking.partner.v2.Booking]
+type GetBookingStatusRequest struct {
+ // ID of the existing booking
+ BookingId string `protobuf:"bytes,1,opt,name=booking_id,json=bookingId" json:"booking_id,omitempty"`
+}
+
+func (m *GetBookingStatusRequest) Reset() { *m = GetBookingStatusRequest{} }
+func (m *GetBookingStatusRequest) String() string { return proto.CompactTextString(m) }
+func (*GetBookingStatusRequest) ProtoMessage() {}
+func (*GetBookingStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
+
+func (m *GetBookingStatusRequest) GetBookingId() string {
+ if m != nil {
+ return m.BookingId
+ }
+ return ""
+}
+
+// Response for the [ext.maps.booking.partner.v2.GetBookingStatus] RPC with
+// booking status and prepayment status
+type GetBookingStatusResponse struct {
+ // ID of the booking
+ BookingId string `protobuf:"bytes,1,opt,name=booking_id,json=bookingId" json:"booking_id,omitempty"`
+ // Status of the booking
+ BookingStatus BookingStatus `protobuf:"varint,2,opt,name=booking_status,json=bookingStatus,enum=ext.maps.booking.partner.v2.BookingStatus" json:"booking_status,omitempty"`
+ // Prepayment status of the booking
+ PrepaymentStatus PrepaymentStatus `protobuf:"varint,3,opt,name=prepayment_status,json=prepaymentStatus,enum=ext.maps.booking.partner.v2.PrepaymentStatus" json:"prepayment_status,omitempty"`
+}
+
+func (m *GetBookingStatusResponse) Reset() { *m = GetBookingStatusResponse{} }
+func (m *GetBookingStatusResponse) String() string { return proto.CompactTextString(m) }
+func (*GetBookingStatusResponse) ProtoMessage() {}
+func (*GetBookingStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} }
+
+func (m *GetBookingStatusResponse) GetBookingId() string {
+ if m != nil {
+ return m.BookingId
+ }
+ return ""
+}
+
+func (m *GetBookingStatusResponse) GetBookingStatus() BookingStatus {
+ if m != nil {
+ return m.BookingStatus
+ }
+ return BookingStatus_BOOKING_STATUS_UNSPECIFIED
+}
+
+func (m *GetBookingStatusResponse) GetPrepaymentStatus() PrepaymentStatus {
+ if m != nil {
+ return m.PrepaymentStatus
+ }
+ return PrepaymentStatus_PREPAYMENT_STATUS_UNSPECIFIED
+}
+
+// Request to list all bookings for a user
+type ListBookingsRequest struct {
+ // ID of the user
+ UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId" json:"user_id,omitempty"`
+}
+
+func (m *ListBookingsRequest) Reset() { *m = ListBookingsRequest{} }
+func (m *ListBookingsRequest) String() string { return proto.CompactTextString(m) }
+func (*ListBookingsRequest) ProtoMessage() {}
+func (*ListBookingsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} }
+
+func (m *ListBookingsRequest) GetUserId() string {
+ if m != nil {
+ return m.UserId
+ }
+ return ""
+}
+
+// Response for the [ext.maps.booking.partner.v2.ListBookings] RPC with all
+// bookings for the requested user
+type ListBookingsResponse struct {
+ // All bookings of the user
+ Bookings []*Booking `protobuf:"bytes,1,rep,name=bookings" json:"bookings,omitempty"`
+}
+
+func (m *ListBookingsResponse) Reset() { *m = ListBookingsResponse{} }
+func (m *ListBookingsResponse) String() string { return proto.CompactTextString(m) }
+func (*ListBookingsResponse) ProtoMessage() {}
+func (*ListBookingsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} }
+
+func (m *ListBookingsResponse) GetBookings() []*Booking {
+ if m != nil {
+ return m.Bookings
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Slot)(nil), "ext.maps.booking.partner.v2.Slot")
+ proto.RegisterType((*Lease)(nil), "ext.maps.booking.partner.v2.Lease")
+ proto.RegisterType((*LeaseReference)(nil), "ext.maps.booking.partner.v2.LeaseReference")
+ proto.RegisterType((*Booking)(nil), "ext.maps.booking.partner.v2.Booking")
+ proto.RegisterType((*UserInformation)(nil), "ext.maps.booking.partner.v2.UserInformation")
+ proto.RegisterType((*PostalAddress)(nil), "ext.maps.booking.partner.v2.PostalAddress")
+ proto.RegisterType((*PaymentProcessingParameters)(nil), "ext.maps.booking.partner.v2.PaymentProcessingParameters")
+ proto.RegisterType((*Price)(nil), "ext.maps.booking.partner.v2.Price")
+ proto.RegisterType((*UserPaymentOption)(nil), "ext.maps.booking.partner.v2.UserPaymentOption")
+ proto.RegisterType((*PaymentInformation)(nil), "ext.maps.booking.partner.v2.PaymentInformation")
+ proto.RegisterType((*BookingFailure)(nil), "ext.maps.booking.partner.v2.BookingFailure")
+ proto.RegisterType((*Resources)(nil), "ext.maps.booking.partner.v2.Resources")
+ proto.RegisterType((*CheckAvailabilityRequest)(nil), "ext.maps.booking.partner.v2.CheckAvailabilityRequest")
+ proto.RegisterType((*CheckAvailabilityResponse)(nil), "ext.maps.booking.partner.v2.CheckAvailabilityResponse")
+ proto.RegisterType((*CreateLeaseRequest)(nil), "ext.maps.booking.partner.v2.CreateLeaseRequest")
+ proto.RegisterType((*CreateLeaseResponse)(nil), "ext.maps.booking.partner.v2.CreateLeaseResponse")
+ proto.RegisterType((*CreateBookingRequest)(nil), "ext.maps.booking.partner.v2.CreateBookingRequest")
+ proto.RegisterType((*CreateBookingResponse)(nil), "ext.maps.booking.partner.v2.CreateBookingResponse")
+ proto.RegisterType((*UpdateBookingRequest)(nil), "ext.maps.booking.partner.v2.UpdateBookingRequest")
+ proto.RegisterType((*UpdateBookingResponse)(nil), "ext.maps.booking.partner.v2.UpdateBookingResponse")
+ proto.RegisterType((*GetBookingStatusRequest)(nil), "ext.maps.booking.partner.v2.GetBookingStatusRequest")
+ proto.RegisterType((*GetBookingStatusResponse)(nil), "ext.maps.booking.partner.v2.GetBookingStatusResponse")
+ proto.RegisterType((*ListBookingsRequest)(nil), "ext.maps.booking.partner.v2.ListBookingsRequest")
+ proto.RegisterType((*ListBookingsResponse)(nil), "ext.maps.booking.partner.v2.ListBookingsResponse")
+ proto.RegisterEnum("ext.maps.booking.partner.v2.PaymentOptionType", PaymentOptionType_name, PaymentOptionType_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.BookingStatus", BookingStatus_name, BookingStatus_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.PrepaymentStatus", PrepaymentStatus_name, PrepaymentStatus_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.PaymentProcessingParameters_PaymentProcessor", PaymentProcessingParameters_PaymentProcessor_name, PaymentProcessingParameters_PaymentProcessor_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.PaymentInformation_PaymentProcessedBy", PaymentInformation_PaymentProcessedBy_name, PaymentInformation_PaymentProcessedBy_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.BookingFailure_Cause", BookingFailure_Cause_name, BookingFailure_Cause_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.BookingFailure_CreditCardType", BookingFailure_CreditCardType_name, BookingFailure_CreditCardType_value)
+ proto.RegisterEnum("ext.maps.booking.partner.v2.CheckAvailabilityResponse_DurationRequirement", CheckAvailabilityResponse_DurationRequirement_name, CheckAvailabilityResponse_DurationRequirement_value)
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// Client API for BookingService service
+
+type BookingServiceClient interface {
+ // Gets availability information for an appointment slot
+ CheckAvailability(ctx context.Context, in *CheckAvailabilityRequest, opts ...grpc.CallOption) (*CheckAvailabilityResponse, error)
+ // Creates a new lease
+ CreateLease(ctx context.Context, in *CreateLeaseRequest, opts ...grpc.CallOption) (*CreateLeaseResponse, error)
+ // Creates a booking
+ CreateBooking(ctx context.Context, in *CreateBookingRequest, opts ...grpc.CallOption) (*CreateBookingResponse, error)
+ // Updates an existing booking
+ UpdateBooking(ctx context.Context, in *UpdateBookingRequest, opts ...grpc.CallOption) (*UpdateBookingResponse, error)
+ // Gets status for an existing booking
+ GetBookingStatus(ctx context.Context, in *GetBookingStatusRequest, opts ...grpc.CallOption) (*GetBookingStatusResponse, error)
+ // Lists all bookings for a user
+ ListBookings(ctx context.Context, in *ListBookingsRequest, opts ...grpc.CallOption) (*ListBookingsResponse, error)
+}
+
+type bookingServiceClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewBookingServiceClient(cc *grpc.ClientConn) BookingServiceClient {
+ return &bookingServiceClient{cc}
+}
+
+func (c *bookingServiceClient) CheckAvailability(ctx context.Context, in *CheckAvailabilityRequest, opts ...grpc.CallOption) (*CheckAvailabilityResponse, error) {
+ out := new(CheckAvailabilityResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/CheckAvailability", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bookingServiceClient) CreateLease(ctx context.Context, in *CreateLeaseRequest, opts ...grpc.CallOption) (*CreateLeaseResponse, error) {
+ out := new(CreateLeaseResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/CreateLease", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bookingServiceClient) CreateBooking(ctx context.Context, in *CreateBookingRequest, opts ...grpc.CallOption) (*CreateBookingResponse, error) {
+ out := new(CreateBookingResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/CreateBooking", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bookingServiceClient) UpdateBooking(ctx context.Context, in *UpdateBookingRequest, opts ...grpc.CallOption) (*UpdateBookingResponse, error) {
+ out := new(UpdateBookingResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/UpdateBooking", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bookingServiceClient) GetBookingStatus(ctx context.Context, in *GetBookingStatusRequest, opts ...grpc.CallOption) (*GetBookingStatusResponse, error) {
+ out := new(GetBookingStatusResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/GetBookingStatus", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bookingServiceClient) ListBookings(ctx context.Context, in *ListBookingsRequest, opts ...grpc.CallOption) (*ListBookingsResponse, error) {
+ out := new(ListBookingsResponse)
+ err := grpc.Invoke(ctx, "/ext.maps.booking.partner.v2.BookingService/ListBookings", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for BookingService service
+
+type BookingServiceServer interface {
+ // Gets availability information for an appointment slot
+ CheckAvailability(context.Context, *CheckAvailabilityRequest) (*CheckAvailabilityResponse, error)
+ // Creates a new lease
+ CreateLease(context.Context, *CreateLeaseRequest) (*CreateLeaseResponse, error)
+ // Creates a booking
+ CreateBooking(context.Context, *CreateBookingRequest) (*CreateBookingResponse, error)
+ // Updates an existing booking
+ UpdateBooking(context.Context, *UpdateBookingRequest) (*UpdateBookingResponse, error)
+ // Gets status for an existing booking
+ GetBookingStatus(context.Context, *GetBookingStatusRequest) (*GetBookingStatusResponse, error)
+ // Lists all bookings for a user
+ ListBookings(context.Context, *ListBookingsRequest) (*ListBookingsResponse, error)
+}
+
+func RegisterBookingServiceServer(s *grpc.Server, srv BookingServiceServer) {
+ s.RegisterService(&_BookingService_serviceDesc, srv)
+}
+
+func _BookingService_CheckAvailability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CheckAvailabilityRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).CheckAvailability(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/CheckAvailability",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).CheckAvailability(ctx, req.(*CheckAvailabilityRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BookingService_CreateLease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateLeaseRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).CreateLease(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/CreateLease",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).CreateLease(ctx, req.(*CreateLeaseRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BookingService_CreateBooking_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateBookingRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).CreateBooking(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/CreateBooking",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).CreateBooking(ctx, req.(*CreateBookingRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BookingService_UpdateBooking_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateBookingRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).UpdateBooking(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/UpdateBooking",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).UpdateBooking(ctx, req.(*UpdateBookingRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BookingService_GetBookingStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetBookingStatusRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).GetBookingStatus(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/GetBookingStatus",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).GetBookingStatus(ctx, req.(*GetBookingStatusRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BookingService_ListBookings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListBookingsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BookingServiceServer).ListBookings(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ext.maps.booking.partner.v2.BookingService/ListBookings",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BookingServiceServer).ListBookings(ctx, req.(*ListBookingsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _BookingService_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "ext.maps.booking.partner.v2.BookingService",
+ HandlerType: (*BookingServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "CheckAvailability",
+ Handler: _BookingService_CheckAvailability_Handler,
+ },
+ {
+ MethodName: "CreateLease",
+ Handler: _BookingService_CreateLease_Handler,
+ },
+ {
+ MethodName: "CreateBooking",
+ Handler: _BookingService_CreateBooking_Handler,
+ },
+ {
+ MethodName: "UpdateBooking",
+ Handler: _BookingService_UpdateBooking_Handler,
+ },
+ {
+ MethodName: "GetBookingStatus",
+ Handler: _BookingService_GetBookingStatus_Handler,
+ },
+ {
+ MethodName: "ListBookings",
+ Handler: _BookingService_ListBookings_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "booking_service.proto",
+}
+
+func init() { proto.RegisterFile("booking_service.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 2368 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x19, 0x4b, 0x6f, 0x1b, 0xc7,
+ 0xd9, 0xa4, 0x48, 0x49, 0xfc, 0x24, 0xd1, 0xab, 0x91, 0x1c, 0xd3, 0x52, 0x1c, 0xcb, 0x9b, 0xb4,
+ 0x4d, 0xed, 0x94, 0x8e, 0x95, 0xb8, 0x70, 0x5b, 0xa0, 0xc8, 0x92, 0x3b, 0x96, 0xd7, 0x25, 0x97,
+ 0xf4, 0xec, 0xd2, 0x8e, 0x73, 0xc8, 0x76, 0xc5, 0x1d, 0xca, 0x5b, 0x93, 0xdc, 0xcd, 0xee, 0x52,
+ 0x90, 0x82, 0xf6, 0x50, 0xa0, 0x40, 0x2f, 0xed, 0x29, 0x87, 0x9e, 0x7a, 0xec, 0xb9, 0xd7, 0x02,
+ 0xfd, 0x13, 0xfd, 0x05, 0x05, 0x0a, 0xf4, 0xd0, 0xfe, 0x85, 0x16, 0x05, 0x8a, 0x79, 0x2c, 0xdf,
+ 0xa2, 0x1e, 0x49, 0x4f, 0xbd, 0x71, 0xbe, 0xd7, 0x7c, 0xef, 0xf9, 0xbe, 0x25, 0xdc, 0x38, 0x0c,
+ 0x82, 0x37, 0x7e, 0xff, 0xc8, 0x89, 0x69, 0x74, 0xec, 0xb7, 0x69, 0x39, 0x8c, 0x82, 0x24, 0x40,
+ 0xbb, 0xf4, 0x24, 0x29, 0xf7, 0xdc, 0x30, 0x2e, 0x4b, 0x7c, 0x39, 0x74, 0xa3, 0xa4, 0x4f, 0xa3,
+ 0xf2, 0xf1, 0xfe, 0xce, 0x3b, 0x47, 0x41, 0x70, 0xd4, 0xa5, 0x0f, 0x38, 0xe9, 0xe1, 0xa0, 0xf3,
+ 0xc0, 0x1b, 0x44, 0x6e, 0xe2, 0x07, 0x7d, 0xc1, 0xbc, 0xb3, 0x37, 0x8d, 0xef, 0xf8, 0xb4, 0xeb,
+ 0x39, 0x3d, 0x37, 0x7e, 0x23, 0x29, 0xee, 0x4c, 0x53, 0x24, 0x7e, 0x8f, 0xc6, 0x89, 0xdb, 0x0b,
+ 0x05, 0x81, 0xfa, 0xc7, 0x2c, 0xe4, 0xac, 0x6e, 0x90, 0xa0, 0x3b, 0xb0, 0xd6, 0xa3, 0x51, 0xfb,
+ 0xb5, 0xdb, 0x4f, 0x1c, 0xdf, 0x2b, 0x65, 0xf6, 0x32, 0xef, 0x17, 0x08, 0xa4, 0x20, 0xc3, 0x43,
+ 0xb7, 0x01, 0xa4, 0xea, 0x0c, 0x9f, 0xe5, 0xf8, 0x82, 0x84, 0x18, 0x1e, 0xfa, 0x01, 0x40, 0x9c,
+ 0xb8, 0x51, 0xe2, 0xb0, 0x1b, 0x4a, 0x4b, 0x7b, 0x99, 0xf7, 0xd7, 0xf6, 0x77, 0xca, 0xe2, 0xfa,
+ 0x72, 0x7a, 0x7d, 0xd9, 0x4e, 0xaf, 0x27, 0x05, 0x4e, 0xcd, 0xce, 0xe8, 0x11, 0xac, 0xa6, 0x86,
+ 0x95, 0x72, 0x9c, 0xf1, 0xd6, 0x0c, 0xa3, 0x2e, 0x09, 0xc8, 0x90, 0x14, 0x7d, 0x17, 0x14, 0xf7,
+ 0xd8, 0xf5, 0xbb, 0xee, 0xa1, 0xdf, 0xf5, 0x93, 0x53, 0x27, 0x71, 0x8f, 0x4a, 0x79, 0xae, 0xd6,
+ 0xf5, 0x71, 0xb8, 0xed, 0x1e, 0x21, 0x1d, 0x0a, 0x11, 0x8d, 0x83, 0x41, 0xd4, 0xa6, 0x71, 0x69,
+ 0x99, 0x5f, 0xf1, 0xed, 0xf2, 0x02, 0xcf, 0x97, 0x49, 0x4a, 0x4d, 0x46, 0x8c, 0xcf, 0x72, 0xab,
+ 0x2b, 0xca, 0xaa, 0xfa, 0x97, 0x0c, 0xe4, 0x6b, 0xd4, 0x8d, 0x29, 0xba, 0x05, 0xab, 0x5d, 0xf6,
+ 0x63, 0xe4, 0xaf, 0x15, 0x7e, 0x36, 0x3c, 0xf4, 0x08, 0x72, 0x71, 0x37, 0x48, 0xb8, 0x9b, 0xd6,
+ 0xf6, 0xef, 0x2e, 0xbc, 0x8b, 0xb9, 0x9f, 0x70, 0x72, 0xf4, 0x2d, 0x28, 0x0e, 0x62, 0x1a, 0x39,
+ 0x11, 0xed, 0xd0, 0x88, 0xf6, 0xdb, 0xc2, 0x91, 0x05, 0xb2, 0xc1, 0xa0, 0x24, 0x05, 0x22, 0x13,
+ 0x6e, 0x88, 0x8b, 0xe9, 0x49, 0xe8, 0x0b, 0x6f, 0x08, 0xb7, 0xe7, 0xce, 0x75, 0xfb, 0x16, 0x67,
+ 0xc4, 0x43, 0x3e, 0x86, 0x51, 0xef, 0x43, 0x91, 0x5b, 0x34, 0xba, 0xe1, 0x6c, 0xd3, 0xd4, 0xbf,
+ 0x66, 0x61, 0xa5, 0x22, 0xac, 0x60, 0x39, 0x91, 0xa6, 0xf5, 0x90, 0xb0, 0x20, 0x21, 0x57, 0xf7,
+ 0xc2, 0x4b, 0x50, 0xb8, 0x17, 0xfc, 0x7e, 0x27, 0x88, 0x7a, 0x22, 0x2f, 0x44, 0x42, 0x7d, 0xb0,
+ 0x50, 0x44, 0x2b, 0xa6, 0x91, 0x31, 0xe2, 0x21, 0xd7, 0x07, 0x93, 0x00, 0x54, 0x81, 0xe5, 0x38,
+ 0x71, 0x93, 0x41, 0xcc, 0x1d, 0x55, 0xdc, 0xbf, 0xb7, 0x50, 0x9c, 0x34, 0xd2, 0xe2, 0x1c, 0x44,
+ 0x72, 0xa2, 0x9f, 0xc2, 0x56, 0xe8, 0x9e, 0xf6, 0x28, 0x2b, 0x93, 0x31, 0xfd, 0xf2, 0x5c, 0xbf,
+ 0x07, 0x0b, 0x05, 0x36, 0x05, 0xdf, 0xb8, 0x8a, 0x28, 0x9c, 0x81, 0xa9, 0x7f, 0xcf, 0xc0, 0xf5,
+ 0x29, 0x53, 0xd0, 0x4d, 0x58, 0x11, 0x2e, 0x49, 0xbd, 0xbc, 0xcc, 0x6d, 0xe3, 0x55, 0x79, 0xe4,
+ 0x1f, 0xd3, 0xbe, 0xd3, 0x77, 0x7b, 0x34, 0xad, 0x4a, 0x0e, 0x31, 0xdd, 0x1e, 0x65, 0x55, 0xdd,
+ 0x71, 0x7b, 0x7e, 0xf7, 0x54, 0xe0, 0x45, 0x36, 0x81, 0x00, 0x71, 0x02, 0x1d, 0x56, 0x5c, 0xcf,
+ 0x8b, 0x68, 0x1c, 0xcb, 0xe4, 0x59, 0xec, 0x93, 0x66, 0x10, 0x27, 0x6e, 0x57, 0x13, 0x1c, 0x24,
+ 0x65, 0x45, 0x6f, 0x43, 0x21, 0xa1, 0x5d, 0x1a, 0xbe, 0x0e, 0xfa, 0x54, 0xd6, 0xe0, 0x08, 0x80,
+ 0xb6, 0x21, 0x4f, 0x7b, 0xae, 0xdf, 0xe5, 0x95, 0x57, 0x20, 0xe2, 0xa0, 0xfe, 0x3a, 0x0b, 0x1b,
+ 0x13, 0xe2, 0xd0, 0x77, 0xe0, 0xba, 0x14, 0xe8, 0xb4, 0x83, 0x41, 0x3f, 0x89, 0x4e, 0xa5, 0xb1,
+ 0x45, 0x09, 0xae, 0x0a, 0x28, 0xaf, 0x7c, 0x49, 0xd8, 0x0d, 0xda, 0x2e, 0xab, 0x72, 0x69, 0x7a,
+ 0x2a, 0xa0, 0x26, 0xc1, 0xac, 0xa2, 0x52, 0xd2, 0x88, 0x1e, 0xa5, 0x99, 0x54, 0x20, 0x1b, 0x12,
+ 0x4a, 0x38, 0x10, 0x7d, 0x04, 0x6f, 0x85, 0x41, 0x9c, 0x38, 0x41, 0xa7, 0xc3, 0x1a, 0xdc, 0x61,
+ 0x70, 0xe2, 0xf4, 0x07, 0xbd, 0x43, 0x1a, 0x71, 0xaf, 0x14, 0xc8, 0x16, 0xc3, 0x36, 0x38, 0xb2,
+ 0x12, 0x9c, 0x98, 0x1c, 0xc5, 0x9c, 0x1b, 0x72, 0x03, 0x9c, 0x76, 0xe0, 0xa5, 0x76, 0x83, 0x00,
+ 0x55, 0x03, 0x8f, 0xb2, 0xcb, 0xe3, 0x24, 0xa2, 0x34, 0x71, 0x52, 0x1f, 0x0b, 0x0f, 0x6c, 0x08,
+ 0xa8, 0xb4, 0x5b, 0xfd, 0x53, 0x16, 0x76, 0x65, 0x6e, 0x34, 0xa3, 0xa0, 0x4d, 0xe3, 0xd8, 0xef,
+ 0x1f, 0x35, 0xdd, 0xc8, 0xed, 0xd1, 0x84, 0x46, 0x31, 0x3a, 0x82, 0x42, 0x28, 0xe0, 0x41, 0xc4,
+ 0x3d, 0x52, 0xdc, 0x37, 0x2e, 0x92, 0x68, 0xf3, 0x84, 0x4d, 0xe1, 0x82, 0x88, 0x8c, 0x64, 0xa3,
+ 0x0f, 0x61, 0x3b, 0xcd, 0xed, 0x1e, 0x4d, 0x5e, 0x07, 0x9e, 0x93, 0x04, 0x6f, 0x68, 0x5f, 0xfa,
+ 0x36, 0xcd, 0xd5, 0x3a, 0x47, 0xd9, 0x0c, 0x83, 0x4a, 0xb0, 0x72, 0x4c, 0xa3, 0x78, 0xe4, 0xd7,
+ 0xf4, 0xa8, 0x7a, 0xa0, 0x4c, 0x5f, 0x85, 0xee, 0xc2, 0xed, 0xa6, 0xf6, 0xaa, 0x8e, 0x4d, 0xdb,
+ 0x69, 0x92, 0x46, 0x15, 0x5b, 0x56, 0x83, 0x38, 0x2d, 0xd3, 0x6a, 0xe2, 0xaa, 0xf1, 0xc4, 0xc0,
+ 0xba, 0x72, 0x0d, 0x6d, 0x83, 0x32, 0x42, 0x59, 0x36, 0x31, 0x9a, 0x58, 0xc9, 0xa0, 0x9b, 0xb0,
+ 0x35, 0x82, 0x56, 0x88, 0x66, 0x98, 0x36, 0xc1, 0x58, 0xc9, 0xaa, 0x0d, 0xc8, 0x37, 0x23, 0xbf,
+ 0x4d, 0xd1, 0x5d, 0x58, 0x0f, 0xd9, 0x0f, 0xa7, 0xe7, 0xb7, 0xa3, 0x20, 0xe6, 0x6e, 0x5a, 0x22,
+ 0x6b, 0x1c, 0x56, 0xe7, 0x20, 0xf4, 0x2e, 0x6c, 0xb4, 0x07, 0x11, 0xeb, 0x6f, 0xa7, 0x22, 0x60,
+ 0xc2, 0xac, 0xf5, 0x14, 0xc8, 0x42, 0xa6, 0xfe, 0x66, 0x09, 0x36, 0x59, 0xf1, 0x49, 0xdd, 0x1b,
+ 0x61, 0x22, 0xd3, 0x83, 0x97, 0x5f, 0xea, 0x9d, 0x80, 0x83, 0x47, 0xd5, 0xb8, 0x35, 0x98, 0x66,
+ 0x31, 0x3c, 0xa4, 0x83, 0x72, 0xec, 0x76, 0x7d, 0xcf, 0x19, 0x7b, 0x17, 0xb3, 0xe7, 0x36, 0xe8,
+ 0x22, 0xe7, 0xb1, 0x86, 0x8f, 0xe3, 0x27, 0x20, 0x20, 0x0e, 0xed, 0x7b, 0x17, 0x7d, 0x5b, 0xd7,
+ 0x39, 0x07, 0xee, 0x7b, 0x5c, 0x42, 0x05, 0x72, 0xc9, 0x69, 0x48, 0x65, 0xcf, 0x2b, 0x5f, 0x24,
+ 0x73, 0x84, 0x0d, 0xf6, 0x69, 0x48, 0x09, 0xe7, 0x65, 0x99, 0x1c, 0x44, 0xfe, 0x91, 0xdf, 0xe7,
+ 0xc9, 0x3e, 0xe8, 0x27, 0x3c, 0xdb, 0xf3, 0x64, 0x23, 0x85, 0xf2, 0xd2, 0x1c, 0xb9, 0x38, 0x91,
+ 0x54, 0xcb, 0x9c, 0x4a, 0xba, 0x38, 0x11, 0x44, 0xf7, 0x60, 0x73, 0xd6, 0x8f, 0x2b, 0xa2, 0x7c,
+ 0xc3, 0x49, 0x1f, 0xaa, 0xff, 0xce, 0x01, 0x9a, 0x6d, 0x9b, 0xe8, 0x33, 0xd8, 0x0c, 0x23, 0x9a,
+ 0x4a, 0x91, 0x3d, 0x5d, 0x54, 0xc6, 0xf7, 0x16, 0xdb, 0x37, 0xe4, 0x92, 0x6d, 0x5d, 0x09, 0xa7,
+ 0x20, 0xe8, 0x63, 0x78, 0x2b, 0x15, 0x9c, 0x44, 0x6e, 0x3f, 0x76, 0xdb, 0xa9, 0x8e, 0x22, 0x5f,
+ 0xd2, 0x12, 0xb1, 0x47, 0x48, 0xc3, 0x43, 0x8f, 0x21, 0xcf, 0x73, 0x4d, 0x46, 0x47, 0x3d, 0x47,
+ 0x0b, 0xbf, 0x4d, 0x89, 0x60, 0x40, 0x1a, 0x40, 0xe2, 0x9e, 0x38, 0x6e, 0x8f, 0x3b, 0x2c, 0x77,
+ 0x61, 0xf6, 0x42, 0xe2, 0x9e, 0x68, 0x9c, 0x09, 0x25, 0xa3, 0xba, 0x95, 0xc5, 0x4c, 0x3d, 0xe7,
+ 0xf0, 0x94, 0xc7, 0xa8, 0xb8, 0x5f, 0xb9, 0xe4, 0xa3, 0x34, 0xd5, 0x22, 0xa8, 0x57, 0x39, 0x1d,
+ 0xd6, 0xfe, 0x18, 0x0c, 0x7d, 0x30, 0x2f, 0x8e, 0xbc, 0xc1, 0x3d, 0xbd, 0x36, 0x13, 0x49, 0xf4,
+ 0xe8, 0xcc, 0x12, 0x5a, 0x91, 0x2c, 0xf3, 0x8a, 0x48, 0xed, 0x0d, 0xe3, 0x3f, 0x7e, 0xf5, 0x7b,
+ 0xb0, 0x37, 0xd5, 0x48, 0xb0, 0xee, 0x54, 0x5e, 0x4d, 0xf5, 0x92, 0x51, 0xd7, 0x10, 0xd8, 0x83,
+ 0x46, 0xe3, 0xa0, 0xc6, 0xda, 0x49, 0x09, 0xb6, 0x27, 0x10, 0x4d, 0x8d, 0xd8, 0x26, 0x26, 0x4a,
+ 0xb6, 0xb2, 0x0e, 0x30, 0x7c, 0xdd, 0x3d, 0xf5, 0xcf, 0x79, 0x28, 0xca, 0x29, 0xe0, 0x89, 0xeb,
+ 0x77, 0x07, 0x11, 0x45, 0x07, 0x90, 0x6f, 0xbb, 0x83, 0x98, 0xca, 0x6c, 0x7b, 0x78, 0x91, 0x09,
+ 0x42, 0xf2, 0x96, 0xab, 0x8c, 0x91, 0x08, 0x7e, 0xf4, 0x1a, 0x50, 0x44, 0x7f, 0x46, 0xdb, 0x09,
+ 0xf5, 0x9c, 0xb6, 0x1b, 0x79, 0x0e, 0xaf, 0xd1, 0x2c, 0x97, 0xfa, 0xc3, 0x4b, 0x49, 0x8d, 0xa8,
+ 0xe7, 0x27, 0x55, 0x37, 0xf2, 0x78, 0xbd, 0x2a, 0xa9, 0xd4, 0x14, 0x82, 0xf6, 0x60, 0xcd, 0xa3,
+ 0x71, 0x3b, 0xf2, 0xc3, 0x64, 0xd4, 0xa7, 0xc7, 0x41, 0xea, 0xdf, 0xb2, 0x90, 0xe7, 0xca, 0xa1,
+ 0x1b, 0xb0, 0x59, 0xd5, 0x5a, 0x16, 0x9e, 0xed, 0xca, 0x56, 0xad, 0x61, 0x3b, 0x2d, 0x53, 0x7b,
+ 0xa1, 0x19, 0x35, 0xad, 0xc2, 0xdd, 0x78, 0x07, 0x76, 0x39, 0x54, 0xab, 0x11, 0xac, 0xe9, 0xaf,
+ 0x9c, 0x4a, 0xa3, 0xf1, 0x13, 0x19, 0x07, 0x8b, 0x79, 0x13, 0x6d, 0xc2, 0x46, 0x0d, 0x6b, 0x16,
+ 0x76, 0xf0, 0xa7, 0x4d, 0x83, 0x60, 0x5d, 0x59, 0x62, 0x3c, 0x8d, 0x96, 0x6d, 0x19, 0x3a, 0x76,
+ 0xaa, 0x9a, 0x59, 0xc5, 0xb5, 0x9a, 0x66, 0x1b, 0x0d, 0xd3, 0x79, 0x69, 0x98, 0x7a, 0xe3, 0xa5,
+ 0x92, 0x1b, 0x0f, 0x2d, 0x26, 0xa4, 0x41, 0x9c, 0xaa, 0x46, 0x74, 0xc7, 0x7e, 0xd5, 0xc4, 0x0e,
+ 0xc1, 0xcf, 0x70, 0xd5, 0xc6, 0xba, 0x92, 0x67, 0x62, 0xe6, 0x50, 0xe9, 0xb8, 0x5a, 0x33, 0x4c,
+ 0xac, 0x2b, 0xcb, 0xe8, 0x6d, 0x28, 0xa5, 0x04, 0x8d, 0x26, 0xbf, 0xc1, 0x6c, 0xd8, 0xce, 0x0b,
+ 0xad, 0x66, 0xe8, 0xca, 0x0a, 0x53, 0x6c, 0x82, 0x5d, 0x59, 0x45, 0x2a, 0xbc, 0xc3, 0xb4, 0x66,
+ 0x5a, 0x31, 0x4a, 0xe6, 0x83, 0x49, 0x01, 0x4a, 0x01, 0xdd, 0x86, 0x5b, 0xcc, 0x46, 0xc3, 0x3c,
+ 0x18, 0xda, 0x2c, 0x8d, 0xc0, 0xba, 0x02, 0x68, 0x17, 0x6e, 0xa6, 0x68, 0x26, 0x22, 0xb5, 0x8f,
+ 0x39, 0x6b, 0x4d, 0x0d, 0xa1, 0x38, 0x19, 0x29, 0xb4, 0x07, 0x6f, 0x57, 0x09, 0xd6, 0x0d, 0x7b,
+ 0xcc, 0xc4, 0x49, 0xb7, 0xaf, 0x42, 0xee, 0x85, 0x61, 0x69, 0x4a, 0x06, 0x15, 0x01, 0xea, 0x9a,
+ 0x65, 0x63, 0xc2, 0x48, 0x95, 0x2c, 0x0b, 0x88, 0x56, 0xc7, 0xc4, 0xa8, 0x6a, 0x26, 0x73, 0x2e,
+ 0xc1, 0x96, 0xa5, 0x2c, 0xa1, 0x75, 0x58, 0xd5, 0x0d, 0xab, 0xda, 0x78, 0x81, 0x89, 0x92, 0x53,
+ 0x3f, 0x87, 0xc2, 0x70, 0x8d, 0x61, 0x03, 0x7d, 0x9c, 0xb8, 0x9d, 0xce, 0xd8, 0x40, 0xcf, 0xcf,
+ 0x86, 0xc7, 0x66, 0xcb, 0x28, 0x08, 0x7a, 0xa3, 0x0e, 0xb7, 0xcc, 0x8e, 0x62, 0xb6, 0x64, 0x69,
+ 0x77, 0xea, 0xc4, 0xfe, 0x97, 0xa2, 0xb1, 0xe5, 0x49, 0x81, 0x43, 0x2c, 0xff, 0x4b, 0xaa, 0x3e,
+ 0x87, 0x52, 0xf5, 0x35, 0x6d, 0xbf, 0xd1, 0xc6, 0x96, 0x2d, 0x42, 0xbf, 0x18, 0xd0, 0x38, 0x19,
+ 0x4e, 0xfe, 0x99, 0x4b, 0x4d, 0xfe, 0xea, 0x3f, 0xb3, 0x70, 0x6b, 0x8e, 0xcc, 0x38, 0x0c, 0xfa,
+ 0x31, 0xbd, 0xa2, 0x50, 0x36, 0x56, 0xf2, 0xc7, 0xc8, 0x91, 0x5b, 0x61, 0x57, 0x94, 0x59, 0x9e,
+ 0x14, 0x39, 0x58, 0x4b, 0xa1, 0xe8, 0x17, 0xb0, 0x9d, 0x2e, 0x97, 0x4e, 0x44, 0xbf, 0x18, 0xf8,
+ 0x11, 0x65, 0x9d, 0x80, 0x5b, 0x5e, 0xdc, 0x7f, 0xb6, 0xf0, 0xbe, 0x33, 0xb5, 0x1e, 0x6d, 0xae,
+ 0x23, 0x89, 0x64, 0xcb, 0x9b, 0x05, 0xaa, 0x3d, 0xd8, 0x9a, 0x43, 0xcb, 0x0a, 0x42, 0x6f, 0x11,
+ 0x51, 0x25, 0x04, 0x3f, 0x6f, 0x19, 0x04, 0xf3, 0xac, 0x9c, 0x4c, 0x95, 0x12, 0x6c, 0xeb, 0x0d,
+ 0x9e, 0x76, 0xd6, 0xd3, 0xc6, 0x4b, 0x27, 0xe5, 0x50, 0x32, 0xe8, 0x2d, 0x40, 0xf5, 0x96, 0x35,
+ 0x0d, 0xcf, 0xaa, 0x26, 0xa0, 0x6a, 0x44, 0xdd, 0x84, 0xca, 0xd5, 0x4f, 0x04, 0xee, 0x31, 0xe4,
+ 0xf9, 0xa2, 0x27, 0x9d, 0xbc, 0xf8, 0x21, 0x12, 0x9c, 0x82, 0x41, 0xfd, 0x43, 0x06, 0xb6, 0x26,
+ 0x04, 0xca, 0xa8, 0x5d, 0x59, 0x22, 0xb2, 0xe1, 0x7a, 0xba, 0x5d, 0x76, 0x44, 0xb3, 0x93, 0xf3,
+ 0xd3, 0xfd, 0x4b, 0xf4, 0x47, 0x52, 0x3c, 0x9c, 0x38, 0xab, 0xff, 0x59, 0x82, 0x6d, 0xa1, 0xa7,
+ 0x24, 0xfc, 0x7a, 0x39, 0x8b, 0x9e, 0x42, 0x41, 0xac, 0xca, 0x11, 0xed, 0x5c, 0x48, 0xbf, 0xc9,
+ 0x55, 0x9b, 0x88, 0x45, 0x9b, 0xd0, 0xce, 0xff, 0x6e, 0xef, 0x3d, 0x63, 0x67, 0xcd, 0x7d, 0x63,
+ 0x3b, 0x2b, 0xfa, 0x39, 0xdc, 0x9e, 0x9a, 0x40, 0x58, 0xd4, 0xc2, 0xe1, 0xda, 0x21, 0xf7, 0xe3,
+ 0xc7, 0x57, 0x5d, 0x5b, 0xc8, 0x6e, 0xb8, 0x60, 0x41, 0xba, 0x0f, 0x9b, 0xbe, 0x47, 0x7b, 0x61,
+ 0x90, 0xf0, 0xe1, 0x5e, 0x2c, 0x2d, 0x62, 0xd5, 0x52, 0xc6, 0x10, 0x7c, 0x65, 0x51, 0x7f, 0x9b,
+ 0x85, 0x1b, 0x53, 0xf1, 0x97, 0x99, 0xfa, 0x63, 0x58, 0x91, 0x5a, 0xc9, 0x1c, 0x78, 0xef, 0x22,
+ 0x79, 0x46, 0x52, 0x26, 0xf4, 0x39, 0x6c, 0xcd, 0x19, 0x71, 0x64, 0x4e, 0x94, 0xcf, 0x0d, 0xe1,
+ 0xc4, 0xe8, 0x43, 0x36, 0x67, 0xa6, 0xa1, 0x79, 0xf5, 0xb0, 0xf4, 0xf5, 0xeb, 0xe1, 0xab, 0x0c,
+ 0x6c, 0xb7, 0x42, 0x6f, 0xb6, 0x1e, 0x7e, 0x04, 0x6b, 0x03, 0x0e, 0xe7, 0x1f, 0x14, 0xa5, 0x4b,
+ 0x66, 0xd7, 0x8e, 0x27, 0x3e, 0xed, 0x7a, 0x75, 0x37, 0x7e, 0x43, 0x40, 0x90, 0xb3, 0xdf, 0xe3,
+ 0xbe, 0xcc, 0x5e, 0xc1, 0x97, 0x3c, 0x4a, 0x53, 0x5a, 0xfd, 0x5f, 0x47, 0xe9, 0x31, 0xdc, 0x3c,
+ 0xa0, 0xc9, 0xe4, 0x27, 0x29, 0x19, 0xa7, 0xc5, 0x1f, 0xe1, 0xd4, 0x7f, 0x64, 0xa0, 0x34, 0xcb,
+ 0x2a, 0x9d, 0x79, 0xce, 0x07, 0xbc, 0xe7, 0x50, 0x1c, 0x7e, 0xb6, 0x16, 0x4b, 0x56, 0xf6, 0xd2,
+ 0x1f, 0xce, 0x36, 0x0e, 0xc7, 0x8f, 0xf3, 0x57, 0xb7, 0xa5, 0x6f, 0x64, 0x75, 0x53, 0xcb, 0xb0,
+ 0x55, 0xf3, 0xe3, 0xd4, 0xd4, 0xa1, 0x83, 0xce, 0xfa, 0x78, 0xa6, 0x7e, 0x0a, 0xdb, 0x93, 0xf4,
+ 0xd2, 0x2b, 0x9f, 0xc0, 0xaa, 0x54, 0x80, 0x6d, 0x95, 0x4b, 0x17, 0xce, 0xb1, 0x21, 0xd7, 0xbd,
+ 0xdf, 0x65, 0x60, 0x73, 0x66, 0x97, 0x46, 0xef, 0xc2, 0x9d, 0xa9, 0xa1, 0x74, 0xce, 0xd0, 0x77,
+ 0x1b, 0x6e, 0x4d, 0x11, 0x59, 0x86, 0x79, 0x50, 0xc3, 0x6c, 0x24, 0x55, 0x32, 0x73, 0x06, 0xdb,
+ 0x7a, 0xab, 0x66, 0x1b, 0x1c, 0x9b, 0x65, 0x33, 0xe5, 0x14, 0xb6, 0x65, 0xd6, 0x8c, 0xba, 0x61,
+ 0x63, 0x9d, 0x53, 0x2c, 0xdd, 0xfb, 0x2a, 0x03, 0x1b, 0x13, 0x01, 0x42, 0xef, 0xc0, 0x4e, 0x3a,
+ 0xb6, 0x5a, 0xb6, 0x66, 0xb7, 0xac, 0x29, 0x85, 0x36, 0xa0, 0x50, 0x6d, 0x98, 0x4f, 0x0c, 0x52,
+ 0xc7, 0xba, 0x92, 0xe1, 0x1f, 0x71, 0xb0, 0xa9, 0x33, 0xf2, 0x3a, 0x26, 0xd5, 0xa7, 0x9a, 0x69,
+ 0x3b, 0x12, 0x2f, 0x47, 0x0b, 0x36, 0x87, 0x8a, 0xe1, 0x97, 0x8f, 0xfc, 0x6b, 0xb0, 0x62, 0x36,
+ 0xf8, 0xf8, 0xa1, 0xe4, 0xd8, 0x82, 0x21, 0x0f, 0x4e, 0x13, 0x9b, 0x5a, 0xcd, 0xf8, 0x8c, 0xcd,
+ 0xf3, 0xf7, 0x7e, 0x9f, 0x01, 0x65, 0x3a, 0xc0, 0xfc, 0x26, 0x82, 0x53, 0x7b, 0xe6, 0xea, 0xc6,
+ 0x57, 0x3c, 0x3c, 0xb6, 0x0b, 0xbe, 0x30, 0x74, 0xae, 0xe5, 0x2e, 0xdc, 0x1c, 0x43, 0xb0, 0xb9,
+ 0x68, 0x88, 0xcc, 0x4e, 0x71, 0x11, 0xfc, 0xa4, 0x65, 0xea, 0x5c, 0xd5, 0x49, 0x84, 0x98, 0xce,
+ 0xb1, 0xae, 0xe4, 0xf6, 0xff, 0x35, 0xda, 0x04, 0x2d, 0xf1, 0x97, 0x07, 0xfa, 0x55, 0x06, 0x36,
+ 0x67, 0xa6, 0x3e, 0xf4, 0xe8, 0xb2, 0x53, 0x22, 0x4f, 0xd1, 0x9d, 0xef, 0x5f, 0x6d, 0xb8, 0x54,
+ 0xaf, 0xa1, 0x08, 0xd6, 0xc6, 0xa6, 0x2e, 0xb4, 0xf8, 0x35, 0x9f, 0x1d, 0xf8, 0x76, 0x3e, 0xbc,
+ 0x38, 0xc3, 0xf0, 0xce, 0x13, 0xd8, 0x98, 0x78, 0x41, 0xd1, 0xc3, 0x0b, 0x08, 0x99, 0x7c, 0x5d,
+ 0x76, 0xf6, 0x2f, 0xc3, 0x32, 0x7e, 0xf3, 0xc4, 0xab, 0x70, 0xce, 0xcd, 0xf3, 0xde, 0xb5, 0x73,
+ 0x6e, 0x9e, 0xfb, 0xe8, 0xa8, 0xd7, 0xd0, 0x2f, 0x33, 0xa0, 0x4c, 0xb7, 0x51, 0xf4, 0xf1, 0x42,
+ 0x51, 0x67, 0x34, 0xec, 0x9d, 0x47, 0x97, 0xe4, 0x1a, 0xea, 0x30, 0x80, 0xf5, 0xf1, 0x7e, 0x85,
+ 0x16, 0xc7, 0x6e, 0x4e, 0x2b, 0xdc, 0x79, 0x78, 0x09, 0x8e, 0xf4, 0xda, 0xc3, 0x65, 0xfe, 0xd6,
+ 0x7f, 0xf4, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x16, 0x9d, 0x8b, 0xc3, 0x1c, 0x00, 0x00,
+}
diff --git a/bookingservice/booking_service.proto b/bookingservice/booking_service.proto
new file mode 100644
index 0000000..e515022
--- /dev/null
+++ b/bookingservice/booking_service.proto
@@ -0,0 +1,569 @@
+syntax = "proto3";
+
+package ext.maps.booking.partner.v2;
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/timestamp.proto";
+
+// Manages slot availability, leases and bookings for an inventory of
+// appointments
+service BookingService {
+ // Gets availability information for an appointment slot
+ rpc CheckAvailability(CheckAvailabilityRequest)
+ returns (CheckAvailabilityResponse) {
+ }
+
+ // Creates a new lease
+ rpc CreateLease(CreateLeaseRequest) returns (CreateLeaseResponse) {
+ }
+
+ // Creates a booking
+ rpc CreateBooking(CreateBookingRequest) returns (CreateBookingResponse) {
+ }
+
+ // Updates an existing booking
+ rpc UpdateBooking(UpdateBookingRequest) returns (UpdateBookingResponse) {
+ }
+
+ // Gets status for an existing booking
+ rpc GetBookingStatus(GetBookingStatusRequest)
+ returns (GetBookingStatusResponse) {
+ }
+
+ // Lists all bookings for a user
+ rpc ListBookings(ListBookingsRequest) returns (ListBookingsResponse) {
+ }
+}
+
+// An inventory slot
+message Slot {
+ // ID of the merchant for the slot
+ string merchant_id = 1;
+
+ // ID of the merchant service
+ string service_id = 2;
+
+ // Start time of the appointment slot
+ google.protobuf.Timestamp start_time = 3;
+
+ // Duration of the appointment slot
+ google.protobuf.Duration duration = 4;
+
+ // Opaque tag that identifies the availability slot and matches the value
+ // provided in the availability feed
+ string availability_tag = 5;
+
+ // The set of resources that disambiguates the appointment slot, e.g. by
+ // indicating the staff member and room selected by the user
+ Resources resources = 6;
+
+ reserved 7;
+}
+
+// Temporary lease for an inventory slot
+message Lease {
+ // ID of the lease.
+ // Not populated in CreateLeaseRequest. The value is chosen by the partner and
+ // has to be returned in the response of CreateLease.
+ string lease_id = 1;
+
+ // The appointment slot that the lease is created for.
+ Slot slot = 2;
+
+ // Unique identifier for this lease, chosen by Reserve with Google. Serves as
+ // an idempotency token for [ext.maps.booking.partner.v2.CreateLease]
+ // requests.
+ string user_reference = 3;
+
+ // Expiration time of the lease
+ google.protobuf.Timestamp lease_expiration_time = 4;
+}
+
+// Reference to a [ext.maps.booking.partner.v2.Lease] that has been created via
+// [ext.maps.booking.partner.v2.CreateLease]
+message LeaseReference {
+ // Lease ID
+ string lease_id = 1;
+}
+
+// A booking for an inventory slot
+message Booking {
+ // ID of this booking
+ string booking_id = 1;
+
+ // The appointment slot of this booking
+ Slot slot = 2;
+
+ // Personal information of the user making the appointment
+ UserInformation user_information = 3;
+
+ // Status of the booking
+ BookingStatus status = 4;
+
+ // Information about payment transactions that relate to the booking.
+ PaymentInformation payment_information = 5;
+}
+
+// Personal information about the person making a booking
+message UserInformation {
+ // Unique ID of the user to the partner, chosen by Reserve with Google.
+ string user_id = 1;
+
+ // Given name of the user
+ string given_name = 2;
+
+ // Family name of the user
+ string family_name = 3;
+
+ // Address of the user (optional)
+ PostalAddress address = 4;
+
+ // Phone number of the user (optional)
+ string telephone = 5;
+
+ // Email address of the user
+ string email = 6;
+}
+
+// Postal address for a user
+message PostalAddress {
+ // The country, e.g. "USA".
+ string address_country = 1;
+ // The locality, e.g. "Mountain View".
+ string address_locality = 2;
+ // The region, e.g. "CA".
+ string address_region = 3;
+ // The post office box number, e.g. "3112", optional.
+ string post_office_box_number = 4;
+ // The postal code, e.g. "94043".
+ string postal_code = 5;
+ // The street address, e.g. "1600 Amphitheatre Pkwy".
+ string street_address = 6;
+}
+
+// Parameters to specify how the partner will process payment for a given
+// booking.
+//
+// A sample request:
+// processor: PROCESSOR_STRIPE
+// payment_method_token: "pk_live_12345abcdef"
+// version: "2017-06-15"
+message PaymentProcessingParameters {
+ enum PaymentProcessor {
+ PAYMENT_PROCESSOR_UNSPECIFIED = 0;
+ PROCESSOR_STRIPE = 1;
+ PROCESSOR_BRAINTREE = 2;
+ }
+ PaymentProcessor processor = 1;
+
+ // The token representing the payment method that will be used to pay
+ // for this booking. This token can be only used once. This token can be
+ // only used for the merchant associated with this booking.
+ //
+ // Each processor may choose its own format for this field.
+ // Stripe uses "pk_live_1234abc..." for live keys and "pk_test_1234abc..."
+ // for test keys.
+ string payment_method_token = 2;
+
+ // The payment processor API version that the given payment token is valid
+ // for.
+ //
+ // Each processor may choose its own format for this field.
+ // Stripe uses a date (e.g. "2017-06-15").
+ string version = 3;
+}
+
+message Price {
+ // The price in micro-units of the currency.
+ // Fractions of smallest currency unit will be rounded using nearest even
+ // rounding. (e.g. For USD 2.5 cents rounded to 2 cents, 3.5 cents rounded to
+ // 4 cents, 0.5 cents rounded to 0 cents, 2.51 cents rounded to 3 cents).
+ int64 price_micros = 1;
+ // The currency of the price that is defined in ISO 4217.
+ string currency_code = 2;
+}
+
+enum PaymentOptionType {
+ PAYMENT_OPTION_TYPE_UNSPECIFIED = 0;
+ PAYMENT_OPTION_SINGLE_USE = 1;
+ PAYMENT_OPTION_MULTI_USE = 2;
+ PAYMENT_OPTION_UNLIMITED_USE = 3;
+}
+
+// This describes a payment option, such as a pack, membership, or
+// single-session pass after it has been purchased by a user. It includes an
+// identifier for the user payment option, as well as some information about
+// the payment option with which it is associated.
+message UserPaymentOption {
+ // A unique identifier for the user payment option. This Id MUST be unique
+ // for all UserPaymentOptions across all merchants and users.
+ string user_payment_option_id = 1;
+ // The user payment option will be valid (usable) between start_time and
+ // end_time. Attempts to use a user payment option to make a booking outside
+ // of this interval will fail.
+ google.protobuf.Timestamp valid_start_time = 2;
+ google.protobuf.Timestamp valid_end_time = 3;
+ // The type of the payment option associated with this user payment option.
+ // This can be unlimited for a membership or subscription, multi-use for a
+ // pack, or single-use.
+ PaymentOptionType type = 4;
+ // The original number of uses for this user payment option when it was
+ // purchased. This value is ignored for unlimited payment options.
+ int32 original_count = 5;
+ // The number of uses remaining for this user payment option. If this number
+ // is 0 for a pack, attempts to use this payment option to make a booking will
+ // fail.
+ int32 current_count = 6;
+ // The id of the payment option that has been used to purchase this user
+ // payment option.
+ string payment_option_id = 7;
+}
+
+// Payment details that are sent when creating a new booking.
+message PaymentInformation {
+ // Prepayment status of the booking.
+ // If the prepayment_status is PREPAYMENT_PROVIDED, then
+ // payment_transaction_id contains the associated unique transaction id for
+ // the purchase.
+ // If the prepayment status is PREPAYMENT_REFUNDED, then
+ // payment_transaction_id contains the associated unique transaction id for
+ // the refund.
+ PrepaymentStatus prepayment_status = 1;
+
+ // Unique identifier for a payment transaction associated with the booking.
+ // Empty if not applicable.
+ string payment_transaction_id = 2;
+
+ // These fields must match the service price (specified in the Services feed)
+ // or the PaymentOption corresponding with this service.
+ // They are included in the booking request and response to verify that
+ // the price indicated in the feed has not changed since the last feed
+ // update.
+ //
+ // The price of the booking, exclusive of any taxes.
+ // Existence of price or taxes does not imply that they have been paid,
+ // prepayment_state should be used for that purpose.
+ Price price = 3;
+ // Taxes that are calculated to be paid for this booking.
+ // If this field is absent the price is assumed to be exempt from or already
+ // inclusive of applicable taxes.
+ Price tax_amount = 4;
+
+ // Who handles payment processing?
+ // If payment is processed by the partner, CreateBooking request will
+ // include additional parameters (PaymentProcessingParameters) indicating
+ // the payment method to be used to process the payment.
+ enum PaymentProcessedBy {
+ PAYMENT_PROCESSED_BY_UNSPECIFIED = 0;
+ PROCESSED_BY_GOOGLE = 1;
+ PROCESSED_BY_PARTNER = 2;
+ }
+ PaymentProcessedBy payment_processed_by = 5;
+
+ // The id of the payment option or user payment option associated with the
+ // booking.
+ // If a payment option is purchased as part of a booking, payment_option_id
+ // will be set with the id of that payment option.
+ // If an already purchased user payment option is being used to pay for a
+ // booking, user_payment_option_id will be set with the id of that user
+ // payment option.
+ // When included as part of a response proto, the user_payment_option_id
+ // should be set and must match the UserPaymentOption that is returned in the
+ // RPC response (e.g. the user_payment_option returned in
+ // CreateBookingResponse).
+ oneof payment_id {
+ // The id of the payment option associated with this booking. If this field
+ // is populated, price (and tax_amount, if applicable) must be populated as
+ // well.
+ string payment_option_id = 6;
+
+ // The id of the user payment option used to pay for this booking.
+ string user_payment_option_id = 7;
+ }
+}
+
+// Status of a booking.
+//
+// Updating booking status does not change the status of the associated payment.
+// Prepayment status updates should be done using the PrepaymentStatus enum.
+//
+// nextID: 6
+enum BookingStatus {
+ // Not specified.
+ BOOKING_STATUS_UNSPECIFIED = 0;
+ // Booking has been confirmed
+ CONFIRMED = 1;
+ // Booking is awaiting confirmation by the merchant before it can transition
+ // into CONFIRMED status
+ PENDING_MERCHANT_CONFIRMATION = 2;
+ // Booking has been canceled on behalf of the user.
+ // The merchant can still trigger a manual refund.
+ CANCELED = 3;
+ // User did not show for the appointment
+ NO_SHOW = 4;
+ // User did not show for the appointment in violation of the cancellation
+ // policy.
+ NO_SHOW_PENALIZED = 5;
+}
+
+// Status data that conveys why (1) creating a lease or (2) creating or updating
+// a booking fails.
+// BookingFailure is intended to primarily capture business logic errors.
+message BookingFailure {
+ enum Cause {
+ // Default value: Don't use; amounts to an "unknown error"
+ CAUSE_UNSPECIFIED = 0;
+ // The referenced availability slot is not available any longer.
+ SLOT_UNAVAILABLE = 1;
+ // The user has already booked an appointment for the referenced
+ // availability slot.
+ SLOT_ALREADY_BOOKED_BY_USER = 2;
+ // The lease (if provided) has expired and cannot be used any longer to
+ // complete the requested booking.
+ LEASE_EXPIRED = 3;
+ // The requested cancellation cannot be performed at the current time due
+ // to time restrictions in the merchant's cancellation policy.
+ OUTSIDE_CANCELLATION_WINDOW = 4;
+ // An error was encountered while processing the payment because the
+ // provided credit card type was not accepted by the merchant. The credit
+ // card type must be supplied in rejected_card_type.
+ PAYMENT_ERROR_CARD_TYPE_REJECTED = 5;
+ // An error was encountered while processing the payment because the
+ // provided credit card was declined.
+ PAYMENT_ERROR_CARD_DECLINED = 6;
+ // An error was encountered with the pack/membership used to pay for the
+ // booking. There could be no valid uses left, it could have expired, etc.
+ PAYMENT_OPTION_NOT_VALID = 7;
+ // An error was encountered while processing the payment for this booking.
+ // Use this value to indicate a general payment related error, only if the
+ // error does not match to a specific payment error above.
+ PAYMENT_ERROR = 8;
+ // User cannot use the given payment option (e.g. user trying to use a
+ // first time price for the second time).
+ USER_CANNOT_USE_PAYMENT_OPTION = 9;
+ // A booking that the user tried to cancel has already been cancelled.
+ BOOKING_ALREADY_CANCELLED = 10;
+ // A booking that the user tried to cancel is not cancellable.
+ BOOKING_NOT_CANCELLABLE = 11;
+ }
+
+ Cause cause = 1;
+
+ // Set if cause is PAYMENT_ERROR_CARD_TYPE_REJECTED to indicate the type of
+ // credit card that was rejected.
+ enum CreditCardType {
+ // Default value. Used if credit card type does not match to one below.
+ CREDIT_CARD_TYPE_UNSPECIFIED = 0;
+ VISA = 1;
+ MASTERCARD = 2;
+ AMERICAN_EXPRESS = 3;
+ DISCOVER = 4;
+ }
+ CreditCardType rejected_card_type = 2;
+
+ // This optional field is used for the partner to include additional
+ // information for debugging purpose only.
+ string description = 3;
+}
+
+// Prepayment status of a booking.
+// Updating payment status will trigger an update on the payment status of the
+// associated booking (if applicable).
+// Currently, the only supported transition is from PREPAYMENT_PROVIDED to
+// PREPAYMENT_REFUNDED, which will initiate a non-reversible refund on the
+// associated payment transaction.
+enum PrepaymentStatus {
+ // Not specified, defaults to PREPAYMENT_NOT_PROVIDED.
+ PREPAYMENT_STATUS_UNSPECIFIED = 0;
+ // The fee for the booking has been paid in advance.
+ PREPAYMENT_PROVIDED = 1;
+ // The fee for the booking has not been paid in advance.
+ PREPAYMENT_NOT_PROVIDED = 2;
+ // The fee was previously PREPAYMENT_PROVIDED but has now been refunded.
+ PREPAYMENT_REFUNDED = 3;
+ // The fee was previously PREPAYMENT_PROVIDED but now has been credited
+ // (user given a UserPaymentOption as a voucher for the booking).
+ // If this is set, the response should also include the updated
+ // UserPaymentOption.
+ PREPAYMENT_CREDITED = 4;
+}
+
+// Resource specification that disambiguates an appointment slot
+message Resources {
+ // The staff ID as provided in the feed or empty if not applicable or no staff
+ // was selected.
+ string staff_id = 1;
+ // The room ID as provided in the feed or empty if not applicable or no room
+ // was selected.
+ string room_id = 2;
+ // For Dining Reservations only: the number of seats requested in the booking.
+ int32 party_size = 3;
+}
+
+// Request to check availability for a [ext.maps.booking.partner.v2.Slot]
+message CheckAvailabilityRequest {
+ // The appointment slot that is being checked
+ Slot slot = 1;
+}
+
+// Response for the [ext.maps.booking.partner.v2.CheckAvailability] RPC with the
+// availability of the appointment slot
+message CheckAvailabilityResponse {
+ // The requested slot.
+ Slot slot = 1;
+ // Number of available spots.
+ // 0 indicates that the appointment slot is not available.
+ int32 count_available = 2;
+ // This enum indicates what requirements exist for the user to acknowledge or
+ // view the requested slots duration/end time.
+ enum DurationRequirement {
+ // The handling of the end time is not specified. This is the default.
+ DURATION_REQUIREMENT_UNSPECIFIED = 0;
+
+ // The end time is not shown to the user.
+ DO_NOT_SHOW_DURATION = 1;
+
+ // The end time has to be shown to the user before an appointment can be
+ // made.
+ MUST_SHOW_DURATION = 2;
+ }
+ // Optionally, return the requirement to show the slots duration and/or
+ // endtime. This field will be ignored if slot is unavailable.
+ DurationRequirement duration_requirement = 3;
+}
+
+// Request to create a [ext.maps.booking.partner.v2.Lease] for a slot in the
+// inventory. The expiration time in the returned Lease may be modified by the
+// backend, e.g. if the requested lease period is too long.
+message CreateLeaseRequest {
+ // The lease to be created with information about the appointment slot
+ Lease lease = 1;
+}
+
+// Response for the [ext.maps.booking.partner.v2.CreateLease] RPC with the
+// created [ext.maps.booking.partner.v2.Lease]
+message CreateLeaseResponse {
+ // The created [ext.maps.booking.partner.v2.Lease]
+ Lease lease = 1;
+
+ // If creating a lease fails, this field should reflect the business logic
+ // error (e.g., slot has become unavailable) and lease field is expected to be
+ // unset.
+ BookingFailure booking_failure = 2;
+}
+
+// Request to create a [ext.maps.booking.partner.v2.Booking] for an inventory
+// slot. Consumes the lease if provided.
+message CreateBookingRequest {
+ // The inventory slot that is being requested to make this booking.
+ // If lease_ref is provided, slot must match the lease; slot is provided for
+ // the partner to verify the lease information.
+ // If lease_ref is absent, then create the booking for the slot.
+ Slot slot = 1;
+
+ // The lease that is being confirmed to make this booking.
+ // If lease_ref is provided, then create the booking using the lease.
+ LeaseReference lease_ref = 2;
+
+ // Personal information of the user making the appointment
+ UserInformation user_information = 3;
+
+ // Information about payments. When payment authorizations are handled by
+ // Google, if the booking request does not succeed, payment authorizations are
+ // automatically canceled.
+ PaymentInformation payment_information = 4;
+
+ // The parameters to be used if the payment is processed by the partner
+ // (i.e. payment_information.payment_processed_by is equal to
+ // PROCESSED_BY_PARTNER).
+ PaymentProcessingParameters payment_processing_parameters = 5;
+
+ // Idempotency token for [ext.maps.booking.partner.v2.CreateBooking] requests.
+ string idempotency_token = 6;
+}
+
+// Response with the created [ext.maps.booking.partner.v2.Booking] for an
+// inventory slot
+message CreateBookingResponse {
+ // The created booking
+ Booking booking = 1;
+
+ // The updated user payment option used in this booking.
+ // If a new payment option was purchased to pay for the booking, this should
+ // be a newly created user payment option.
+ // If an already purchased user payment option was used for this booking,
+ // this should reflect an updated version of that user payment option.
+ UserPaymentOption user_payment_option = 2;
+
+ // If creating a booking fails, this field should reflect the business logic
+ // error (e.g., slot has become unavailable) and all other fields in the
+ // CreateBookingResponse message are expected to be unset.
+ BookingFailure booking_failure = 3;
+}
+
+// Request to update a [ext.maps.booking.partner.v2.Booking]
+message UpdateBookingRequest {
+ // Field mask of all booking fields to be updated
+ google.protobuf.FieldMask update_mask = 1;
+
+ // The booking to be updated
+ // The following fields can be set in a booking:
+ // - status, to cancel a booking.
+ // - start_time and duration in the slot, to reschedule a booking.
+ Booking booking = 2;
+}
+
+// Response with the updated [ext.maps.booking.partner.v2.Booking]
+message UpdateBookingResponse {
+ // The updated booking
+ Booking booking = 1;
+
+ // The updated user payment option originally used to pay for this booking.
+ // This should be set if the UpdateBookingRequest results in a change to
+ // the UserPaymentOption.
+ // For instance, if the booking is canceled, the UserPaymentOption should
+ // reflect an additional credit to the user. In the case of a multi-use
+ // payment option, the current_count should be increased by one to
+ // allow the user to create another booking with this payment option. In the
+ // case of a single-use payment option, a new single-use user payment option
+ // should be returned.
+ UserPaymentOption user_payment_option = 2;
+
+ // If updating a booking fails, this field should reflect the business logic
+ // error (e.g., booking is not cancellable)
+ BookingFailure booking_failure = 3;
+}
+
+// Request to get booking status and prepayment status for a
+// [ext.maps.booking.partner.v2.Booking]
+message GetBookingStatusRequest {
+ // ID of the existing booking
+ string booking_id = 1;
+}
+
+// Response for the [ext.maps.booking.partner.v2.GetBookingStatus] RPC with
+// booking status and prepayment status
+message GetBookingStatusResponse {
+ // ID of the booking
+ string booking_id = 1;
+
+ // Status of the booking
+ BookingStatus booking_status = 2;
+
+ // Prepayment status of the booking
+ PrepaymentStatus prepayment_status = 3;
+}
+
+// Request to list all bookings for a user
+message ListBookingsRequest {
+ // ID of the user
+ string user_id = 1;
+}
+
+// Response for the [ext.maps.booking.partner.v2.ListBookings] RPC with all
+// bookings for the requested user
+message ListBookingsResponse {
+ // All bookings of the user
+ repeated Booking bookings = 1;
+}
\ No newline at end of file
diff --git a/feeds/availability_feed.pb.go b/feeds/availability_feed.pb.go
new file mode 100644
index 0000000..c41f821
--- /dev/null
+++ b/feeds/availability_feed.pb.go
@@ -0,0 +1,637 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: availability_feed.proto
+
+/*
+Package maps_booking_feeds is a generated protocol buffer package.
+
+It is generated from these files:
+ availability_feed.proto
+
+It has these top-level messages:
+ FeedMetadata
+ AvailabilityFeed
+ ServiceAvailability
+ Availability
+ Resources
+ TimeRange
+*/
+package maps_booking_feeds
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type FeedMetadata_ProcessingInstruction int32
+
+const (
+ // By default we will assume that this feed is an incremental feed.
+ FeedMetadata_PROCESS_UNKNOWN FeedMetadata_ProcessingInstruction = 0
+ // This Feed message is one shard of a complete feed. Anything previously
+ // supplied by this partner will be deleted; the contents of this feed
+ // represent the entire state of the world.
+ FeedMetadata_PROCESS_AS_COMPLETE FeedMetadata_ProcessingInstruction = 1
+ // This Feed message is one shard of an incremental feed. Existing entities
+ // will be left untouched except as modified in this feed.
+ FeedMetadata_PROCESS_AS_INCREMENTAL FeedMetadata_ProcessingInstruction = 2
+)
+
+var FeedMetadata_ProcessingInstruction_name = map[int32]string{
+ 0: "PROCESS_UNKNOWN",
+ 1: "PROCESS_AS_COMPLETE",
+ 2: "PROCESS_AS_INCREMENTAL",
+}
+var FeedMetadata_ProcessingInstruction_value = map[string]int32{
+ "PROCESS_UNKNOWN": 0,
+ "PROCESS_AS_COMPLETE": 1,
+ "PROCESS_AS_INCREMENTAL": 2,
+}
+
+func (x FeedMetadata_ProcessingInstruction) String() string {
+ return proto.EnumName(FeedMetadata_ProcessingInstruction_name, int32(x))
+}
+func (FeedMetadata_ProcessingInstruction) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{0, 0}
+}
+
+type FeedMetadata struct {
+ // Instructs us how to process the feed: either as a shard of a complete feed,
+ // or as a shard of an incremental update.
+ ProcessingInstruction FeedMetadata_ProcessingInstruction `protobuf:"varint,1,opt,name=processing_instruction,json=processingInstruction,enum=maps.booking.feeds.FeedMetadata_ProcessingInstruction" json:"processing_instruction,omitempty"`
+ // The current shard and total number of shards for this feed.
+ //
+ // Shard number is assumed to be zero-based.
+ //
+ // There does not need to be any relationship to the file name.
+ //
+ // Shards do not need to be transferred in order, and they may not be
+ // processed in order.
+ ShardNumber int32 `protobuf:"varint,2,opt,name=shard_number,json=shardNumber" json:"shard_number,omitempty"`
+ TotalShards int32 `protobuf:"varint,3,opt,name=total_shards,json=totalShards" json:"total_shards,omitempty"`
+ // An identifier that must be consistent across all shards in a feed.
+ // This value must be globally unique across each feed type.
+ //
+ // This value ensures that complete feeds spanning multiple shards are
+ // processed together correctly.
+ //
+ // Clients only need to set this value when the processing_instruction is set
+ // to PROCESS_AS_COMPLETE and the feed spans multiple shards (defined by
+ // total_shards).
+ //
+ // Feeds that span multiple shards must set this nonce to the same value.
+ Nonce uint64 `protobuf:"varint,5,opt,name=nonce" json:"nonce,omitempty"`
+ // The timestamp at which this feed shard was generated.
+ //
+ // In Unix time format (seconds since the epoch).
+ GenerationTimestamp int64 `protobuf:"varint,4,opt,name=generation_timestamp,json=generationTimestamp" json:"generation_timestamp,omitempty"`
+}
+
+func (m *FeedMetadata) Reset() { *m = FeedMetadata{} }
+func (m *FeedMetadata) String() string { return proto.CompactTextString(m) }
+func (*FeedMetadata) ProtoMessage() {}
+func (*FeedMetadata) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *FeedMetadata) GetProcessingInstruction() FeedMetadata_ProcessingInstruction {
+ if m != nil {
+ return m.ProcessingInstruction
+ }
+ return FeedMetadata_PROCESS_UNKNOWN
+}
+
+func (m *FeedMetadata) GetShardNumber() int32 {
+ if m != nil {
+ return m.ShardNumber
+ }
+ return 0
+}
+
+func (m *FeedMetadata) GetTotalShards() int32 {
+ if m != nil {
+ return m.TotalShards
+ }
+ return 0
+}
+
+func (m *FeedMetadata) GetNonce() uint64 {
+ if m != nil {
+ return m.Nonce
+ }
+ return 0
+}
+
+func (m *FeedMetadata) GetGenerationTimestamp() int64 {
+ if m != nil {
+ return m.GenerationTimestamp
+ }
+ return 0
+}
+
+type AvailabilityFeed struct {
+ Metadata *FeedMetadata `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
+ ServiceAvailability []*ServiceAvailability `protobuf:"bytes,2,rep,name=service_availability,json=serviceAvailability" json:"service_availability,omitempty"`
+}
+
+func (m *AvailabilityFeed) Reset() { *m = AvailabilityFeed{} }
+func (m *AvailabilityFeed) String() string { return proto.CompactTextString(m) }
+func (*AvailabilityFeed) ProtoMessage() {}
+func (*AvailabilityFeed) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *AvailabilityFeed) GetMetadata() *FeedMetadata {
+ if m != nil {
+ return m.Metadata
+ }
+ return nil
+}
+
+func (m *AvailabilityFeed) GetServiceAvailability() []*ServiceAvailability {
+ if m != nil {
+ return m.ServiceAvailability
+ }
+ return nil
+}
+
+type ServiceAvailability struct {
+ // If provided, we will consider the Availability entities provided to be a
+ // complete snapshot from [start_timestamp_restrict, end_timestamp_restrict).
+ // That is, all existing availability will be deleted if the following
+ // condition holds true:
+ //
+ // start_timestamp_restrict <= Availability.start_sec &&
+ // Availability.start_sec < end_timestamp_restrict
+ //
+ // If a resource_restrict message is set, the condition is further restricted:
+ //
+ // Availability.resource.staff_id == resource_restrict.staff_id &&
+ // Availability.resource.room_id == resource_restrict.room_id
+ //
+ // These fields are typically used to provide a complete update of
+ // availability in a given time range.
+ //
+ // Setting start_timestamp_restrict while leaving end_timestamp_restrict unset
+ // is interpreted to mean all time beginning at start_timestamp_restrict.
+ //
+ // Setting end_timestamp_restrict while leaving start_timestamp_restrict unset
+ // is interpreted to mean all time up to the end_timestamp_restrict.
+ //
+ // In Unix time format (seconds since the epoch).
+ StartTimestampRestrict int64 `protobuf:"varint,1,opt,name=start_timestamp_restrict,json=startTimestampRestrict" json:"start_timestamp_restrict,omitempty"`
+ EndTimestampRestrict int64 `protobuf:"varint,2,opt,name=end_timestamp_restrict,json=endTimestampRestrict" json:"end_timestamp_restrict,omitempty"`
+ // If provided, the timestamp restricts will be applied only to the given
+ // merchant or service.
+ //
+ // These fields are typically used to provide complete snapshot of
+ // availability in a given range (defined above) for a specific merchant or
+ // service.
+ //
+ // Leaving these fields unset, or setting these to the empty string or null,
+ // is interpreted to mean that no restrict is intended.
+ MerchantIdRestrict string `protobuf:"bytes,3,opt,name=merchant_id_restrict,json=merchantIdRestrict" json:"merchant_id_restrict,omitempty"`
+ ServiceIdRestrict string `protobuf:"bytes,4,opt,name=service_id_restrict,json=serviceIdRestrict" json:"service_id_restrict,omitempty"`
+ // Setting resources_restrict further restricts the scope of the update to
+ // just this set of resources. All id fields of the resources must match
+ // exactly.
+ ResourcesRestrict *Resources `protobuf:"bytes,6,opt,name=resources_restrict,json=resourcesRestrict" json:"resources_restrict,omitempty"`
+ Availability []*Availability `protobuf:"bytes,5,rep,name=availability" json:"availability,omitempty"`
+}
+
+func (m *ServiceAvailability) Reset() { *m = ServiceAvailability{} }
+func (m *ServiceAvailability) String() string { return proto.CompactTextString(m) }
+func (*ServiceAvailability) ProtoMessage() {}
+func (*ServiceAvailability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *ServiceAvailability) GetStartTimestampRestrict() int64 {
+ if m != nil {
+ return m.StartTimestampRestrict
+ }
+ return 0
+}
+
+func (m *ServiceAvailability) GetEndTimestampRestrict() int64 {
+ if m != nil {
+ return m.EndTimestampRestrict
+ }
+ return 0
+}
+
+func (m *ServiceAvailability) GetMerchantIdRestrict() string {
+ if m != nil {
+ return m.MerchantIdRestrict
+ }
+ return ""
+}
+
+func (m *ServiceAvailability) GetServiceIdRestrict() string {
+ if m != nil {
+ return m.ServiceIdRestrict
+ }
+ return ""
+}
+
+func (m *ServiceAvailability) GetResourcesRestrict() *Resources {
+ if m != nil {
+ return m.ResourcesRestrict
+ }
+ return nil
+}
+
+func (m *ServiceAvailability) GetAvailability() []*Availability {
+ if m != nil {
+ return m.Availability
+ }
+ return nil
+}
+
+// An availability of the merchant's service, indicating time and number
+// of spots.
+// The availability feed should be a list of this message.
+// Please note that it's up to the partner to call out all the possible
+// availabilities.
+// If a massage therapist is available 9am-12pm, and they provide
+// one-hour massage sessions, the aggregator should provide the feed as
+// availability {start_sec: 9am, duration: 60 minutes, ...}
+// availability {start_sec: 10am, duration: 60 minutes, ...}
+// availability {start_sec: 11am, duration: 60 minutes, ...}
+// instead of
+// availability {start_sec: 9am, duration: 180 minutes, ...}
+//
+type Availability struct {
+ // An opaque string from an aggregator to identify a merchant.
+ MerchantId string `protobuf:"bytes,1,opt,name=merchant_id,json=merchantId" json:"merchant_id,omitempty"`
+ // An opaque string from aggregator to identify a service of the
+ // merchant.
+ ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId" json:"service_id,omitempty"`
+ // Start time of this availability, using epoch time in seconds.
+ StartSec int64 `protobuf:"varint,3,opt,name=start_sec,json=startSec" json:"start_sec,omitempty"`
+ // Duration of the service in seconds, e.g. 30 minutes for a chair massage.
+ DurationSec int64 `protobuf:"varint,4,opt,name=duration_sec,json=durationSec" json:"duration_sec,omitempty"`
+ // Number of total spots and open spots of this availability.
+ // E.g. a Yoga class of 10 spots with 3 booked.
+ // availability {spots_total: 10, spots_open: 7 ...}
+ // E.g. a chair massage session which was already booked.
+ // availability {spots_total: 1, spots_open: 0 ...}
+ //
+ // Note: If sending requests using the availability compression format defined
+ // below, these two fields will be inferred. A Recurrence
+ // implies spots_total=1 and spots_open=1. A ScheduleException implies
+ // spots_total=1 and spots_open=0.
+ SpotsTotal int64 `protobuf:"varint,5,opt,name=spots_total,json=spotsTotal" json:"spots_total,omitempty"`
+ SpotsOpen int64 `protobuf:"varint,6,opt,name=spots_open,json=spotsOpen" json:"spots_open,omitempty"`
+ // An optional opaque string to identify this availability slot. If set, it
+ // will be included in the requests that book/update/cancel appointments.
+ AvailabilityTag string `protobuf:"bytes,7,opt,name=availability_tag,json=availabilityTag" json:"availability_tag,omitempty"`
+ // Optional resources used to disambiguate this availability slot from
+ // others when different staff, room, or party_size values are part
+ // of the service.
+ //
+ // E.g. the same Yoga class with two 2 instructors.
+ // availability { resources { staff_id: "1" staff_name: "Amy" }
+ // spots_total: 10 spots_open: 7 }
+ // availability { resources { staff_id: "2" staff_name: "John" }
+ // spots_total: 5 spots_open: 2 }
+ Resources *Resources `protobuf:"bytes,8,opt,name=resources" json:"resources,omitempty"`
+ // A list of ids referencing the payment options which can be used to pay
+ // for this slot. The actual payment options are defined at the Merchant
+ // level, and can also be shared among multiple Merchants.
+ //
+ // This field overrides any payment_option_ids specified in the service
+ // message. Similarly payment_option_ids specified here do NOT have to be
+ // present in the service message, though must be defined at the
+ // Merchant level.
+ PaymentOptionId []string `protobuf:"bytes,9,rep,name=payment_option_id,json=paymentOptionId" json:"payment_option_id,omitempty"`
+ // The recurrence information for the availability, representing more than one
+ // start time. A recurrence should contain appointments for one working day.
+ Recurrence *Availability_Recurrence `protobuf:"bytes,10,opt,name=recurrence" json:"recurrence,omitempty"`
+ // When this service cannot be scheduled. To limit the number of
+ // schedule_exception messages consider joining adjacent exceptions.
+ ScheduleException []*Availability_ScheduleException `protobuf:"bytes,11,rep,name=schedule_exception,json=scheduleException" json:"schedule_exception,omitempty"`
+}
+
+func (m *Availability) Reset() { *m = Availability{} }
+func (m *Availability) String() string { return proto.CompactTextString(m) }
+func (*Availability) ProtoMessage() {}
+func (*Availability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *Availability) GetMerchantId() string {
+ if m != nil {
+ return m.MerchantId
+ }
+ return ""
+}
+
+func (m *Availability) GetServiceId() string {
+ if m != nil {
+ return m.ServiceId
+ }
+ return ""
+}
+
+func (m *Availability) GetStartSec() int64 {
+ if m != nil {
+ return m.StartSec
+ }
+ return 0
+}
+
+func (m *Availability) GetDurationSec() int64 {
+ if m != nil {
+ return m.DurationSec
+ }
+ return 0
+}
+
+func (m *Availability) GetSpotsTotal() int64 {
+ if m != nil {
+ return m.SpotsTotal
+ }
+ return 0
+}
+
+func (m *Availability) GetSpotsOpen() int64 {
+ if m != nil {
+ return m.SpotsOpen
+ }
+ return 0
+}
+
+func (m *Availability) GetAvailabilityTag() string {
+ if m != nil {
+ return m.AvailabilityTag
+ }
+ return ""
+}
+
+func (m *Availability) GetResources() *Resources {
+ if m != nil {
+ return m.Resources
+ }
+ return nil
+}
+
+func (m *Availability) GetPaymentOptionId() []string {
+ if m != nil {
+ return m.PaymentOptionId
+ }
+ return nil
+}
+
+func (m *Availability) GetRecurrence() *Availability_Recurrence {
+ if m != nil {
+ return m.Recurrence
+ }
+ return nil
+}
+
+func (m *Availability) GetScheduleException() []*Availability_ScheduleException {
+ if m != nil {
+ return m.ScheduleException
+ }
+ return nil
+}
+
+// Recurrence messages are optional, but allow for a more compact
+// representation of consistently repeating availability slots. They typically
+// represent a day's working schedule.
+// ScheduleException messages are then used to represent booked/unavailable
+// time ranges within the work day.
+//
+// Requirements:
+// 1. The expansion of availability slots or recurrences must NOT create
+// identical slots. If the ids, start_sec, duration_sec, and resources
+// match, slots are considered identical.
+// 2. Do NOT mix the standard availability format and recurrence within the
+// slots of a single service. Recurrence benefits merchants/services that
+// offer appointments. The standard format is geared towards
+// merchants/services with regularly scheduled classes.
+type Availability_Recurrence struct {
+ // The inclusive maximum UTC timestamp the availability repeats until.
+ RepeatUntilSec int64 `protobuf:"varint,1,opt,name=repeat_until_sec,json=repeatUntilSec" json:"repeat_until_sec,omitempty"`
+ // Defines the time between successive availability slots.
+ //
+ // E.g. An availability with a duration of 20 min, a repeat_every_sec of
+ // 30 min, a start_sec of 9:00am, and a repeat_until_sec of 11:00am will
+ // yield slots at 9-9:20am, 9:30-9:50am, 10-10:20am, 10:30-10:50am,
+ // 11-11:20am.
+ RepeatEverySec int32 `protobuf:"varint,2,opt,name=repeat_every_sec,json=repeatEverySec" json:"repeat_every_sec,omitempty"`
+}
+
+func (m *Availability_Recurrence) Reset() { *m = Availability_Recurrence{} }
+func (m *Availability_Recurrence) String() string { return proto.CompactTextString(m) }
+func (*Availability_Recurrence) ProtoMessage() {}
+func (*Availability_Recurrence) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} }
+
+func (m *Availability_Recurrence) GetRepeatUntilSec() int64 {
+ if m != nil {
+ return m.RepeatUntilSec
+ }
+ return 0
+}
+
+func (m *Availability_Recurrence) GetRepeatEverySec() int32 {
+ if m != nil {
+ return m.RepeatEverySec
+ }
+ return 0
+}
+
+// ScheduleException messages are used to represent booked/unavailable time
+// ranges within the work day. As time slots are booked, the list of
+// exceptions should grow to reflect the newly unavailable time ranges.
+// The recurrence itself shouldn't be modified.
+type Availability_ScheduleException struct {
+ // The time range of the exception.
+ TimeRange *TimeRange `protobuf:"bytes,1,opt,name=time_range,json=timeRange" json:"time_range,omitempty"`
+}
+
+func (m *Availability_ScheduleException) Reset() { *m = Availability_ScheduleException{} }
+func (m *Availability_ScheduleException) String() string { return proto.CompactTextString(m) }
+func (*Availability_ScheduleException) ProtoMessage() {}
+func (*Availability_ScheduleException) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{3, 1}
+}
+
+func (m *Availability_ScheduleException) GetTimeRange() *TimeRange {
+ if m != nil {
+ return m.TimeRange
+ }
+ return nil
+}
+
+// A resource is used to disambiguate availability slots from one another when
+// different staff, room or party_size values are part of the service.
+// Multiple slots for the same service and time interval can co-exist when they
+// have different resources.
+type Resources struct {
+ // Optional id for a staff member providing the service. This field identifies
+ // the staff member across all merchants, services, and availability records.
+ // It also needs to be stable over time to allow correlation with past
+ // bookings.
+ // This field must be present if staff_name is present.
+ StaffId string `protobuf:"bytes,1,opt,name=staff_id,json=staffId" json:"staff_id,omitempty"`
+ // Optional name of a staff member providing the service. This field will be
+ // displayed to users making a booking, and should be human readable, as
+ // opposed to an opaque identifier.
+ // This field must be present if staff_id is present.
+ StaffName string `protobuf:"bytes,2,opt,name=staff_name,json=staffName" json:"staff_name,omitempty"`
+ // An optional id for the room the service is located in. This field
+ // identifies the room across all merchants, services, and availability
+ // records. It also needs to be stable over time to allow correlation with
+ // past bookings.
+ // This field must be present if room_name is present.
+ RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId" json:"room_id,omitempty"`
+ // An optional name for the room the service is located in. This
+ // field will be displayed to users making a booking, and should be human
+ // readable, as opposed to an opaque identifier.
+ // This field must be present if room_id is present.
+ RoomName string `protobuf:"bytes,4,opt,name=room_name,json=roomName" json:"room_name,omitempty"`
+ // Applicable only for Dining: The party size which can be accommodated
+ // during this time slot. A restaurant can be associated with multiple Slots
+ // for the same time, each specifying a different party_size, if for instance
+ // 2, 3, or 4 people can be seated with a reservation.
+ PartySize int32 `protobuf:"varint,5,opt,name=party_size,json=partySize" json:"party_size,omitempty"`
+}
+
+func (m *Resources) Reset() { *m = Resources{} }
+func (m *Resources) String() string { return proto.CompactTextString(m) }
+func (*Resources) ProtoMessage() {}
+func (*Resources) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *Resources) GetStaffId() string {
+ if m != nil {
+ return m.StaffId
+ }
+ return ""
+}
+
+func (m *Resources) GetStaffName() string {
+ if m != nil {
+ return m.StaffName
+ }
+ return ""
+}
+
+func (m *Resources) GetRoomId() string {
+ if m != nil {
+ return m.RoomId
+ }
+ return ""
+}
+
+func (m *Resources) GetRoomName() string {
+ if m != nil {
+ return m.RoomName
+ }
+ return ""
+}
+
+func (m *Resources) GetPartySize() int32 {
+ if m != nil {
+ return m.PartySize
+ }
+ return 0
+}
+
+type TimeRange struct {
+ BeginSec int64 `protobuf:"varint,1,opt,name=begin_sec,json=beginSec" json:"begin_sec,omitempty"`
+ EndSec int64 `protobuf:"varint,2,opt,name=end_sec,json=endSec" json:"end_sec,omitempty"`
+}
+
+func (m *TimeRange) Reset() { *m = TimeRange{} }
+func (m *TimeRange) String() string { return proto.CompactTextString(m) }
+func (*TimeRange) ProtoMessage() {}
+func (*TimeRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *TimeRange) GetBeginSec() int64 {
+ if m != nil {
+ return m.BeginSec
+ }
+ return 0
+}
+
+func (m *TimeRange) GetEndSec() int64 {
+ if m != nil {
+ return m.EndSec
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*FeedMetadata)(nil), "maps.booking.feeds.FeedMetadata")
+ proto.RegisterType((*AvailabilityFeed)(nil), "maps.booking.feeds.AvailabilityFeed")
+ proto.RegisterType((*ServiceAvailability)(nil), "maps.booking.feeds.ServiceAvailability")
+ proto.RegisterType((*Availability)(nil), "maps.booking.feeds.Availability")
+ proto.RegisterType((*Availability_Recurrence)(nil), "maps.booking.feeds.Availability.Recurrence")
+ proto.RegisterType((*Availability_ScheduleException)(nil), "maps.booking.feeds.Availability.ScheduleException")
+ proto.RegisterType((*Resources)(nil), "maps.booking.feeds.Resources")
+ proto.RegisterType((*TimeRange)(nil), "maps.booking.feeds.TimeRange")
+ proto.RegisterEnum("maps.booking.feeds.FeedMetadata_ProcessingInstruction", FeedMetadata_ProcessingInstruction_name, FeedMetadata_ProcessingInstruction_value)
+}
+
+func init() { proto.RegisterFile("availability_feed.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 859 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xdb, 0x6e, 0x23, 0x45,
+ 0x10, 0xc5, 0x76, 0x9c, 0x64, 0xca, 0xd1, 0xae, 0xdd, 0xf6, 0x26, 0x43, 0x50, 0xb4, 0xc6, 0x2f,
+ 0x18, 0x90, 0x2c, 0x08, 0x08, 0x21, 0xb1, 0x2f, 0x51, 0x30, 0x52, 0xb4, 0x89, 0x1d, 0x7a, 0xbc,
+ 0x42, 0xe2, 0x65, 0x68, 0xcf, 0x54, 0x9c, 0x11, 0x9e, 0x9e, 0x51, 0x77, 0x3b, 0x22, 0xfb, 0x29,
+ 0x7c, 0x03, 0xff, 0xc1, 0xe7, 0xf0, 0x01, 0xbc, 0xa0, 0xae, 0xb9, 0x9a, 0x58, 0xca, 0xbe, 0x79,
+ 0x4e, 0x9d, 0xd3, 0x97, 0x73, 0xaa, 0xda, 0x70, 0x22, 0x1e, 0x44, 0xb4, 0x16, 0xcb, 0x68, 0x1d,
+ 0x99, 0x47, 0xff, 0x0e, 0x31, 0x9c, 0xa4, 0x2a, 0x31, 0x09, 0x63, 0xb1, 0x48, 0xf5, 0x64, 0x99,
+ 0x24, 0xbf, 0x47, 0x72, 0x35, 0xb1, 0x05, 0x3d, 0xfa, 0xa7, 0x09, 0x47, 0x3f, 0x21, 0x86, 0x37,
+ 0x68, 0x44, 0x28, 0x8c, 0x60, 0x31, 0x1c, 0xa7, 0x2a, 0x09, 0x50, 0xeb, 0x48, 0xae, 0xfc, 0x48,
+ 0x6a, 0xa3, 0x36, 0x81, 0x89, 0x12, 0xe9, 0x36, 0x86, 0x8d, 0xf1, 0x8b, 0xf3, 0xef, 0x26, 0x4f,
+ 0x57, 0x99, 0xd4, 0x57, 0x98, 0xdc, 0x96, 0xf2, 0xab, 0x4a, 0xcd, 0x5f, 0xa5, 0xbb, 0x60, 0xf6,
+ 0x29, 0x1c, 0xe9, 0x7b, 0xa1, 0x42, 0x5f, 0x6e, 0xe2, 0x25, 0x2a, 0xb7, 0x39, 0x6c, 0x8c, 0xdb,
+ 0xbc, 0x43, 0xd8, 0x8c, 0x20, 0x4b, 0x31, 0x89, 0x11, 0x6b, 0x9f, 0x40, 0xed, 0xb6, 0x32, 0x0a,
+ 0x61, 0x1e, 0x41, 0x6c, 0x00, 0x6d, 0x99, 0xc8, 0x00, 0xdd, 0xf6, 0xb0, 0x31, 0xde, 0xe3, 0xd9,
+ 0x07, 0xfb, 0x1a, 0x06, 0x2b, 0x94, 0xa8, 0x84, 0xdd, 0xc9, 0x37, 0x51, 0x8c, 0xda, 0x88, 0x38,
+ 0x75, 0xf7, 0x86, 0x8d, 0x71, 0x8b, 0xf7, 0xab, 0xda, 0xa2, 0x28, 0x8d, 0x04, 0xbc, 0xda, 0x79,
+ 0x7c, 0xd6, 0x87, 0x97, 0xb7, 0x7c, 0x7e, 0x39, 0xf5, 0x3c, 0xff, 0xdd, 0xec, 0xed, 0x6c, 0xfe,
+ 0xcb, 0xac, 0xfb, 0x11, 0x3b, 0x81, 0x7e, 0x01, 0x5e, 0x78, 0xfe, 0xe5, 0xfc, 0xe6, 0xf6, 0x7a,
+ 0xba, 0x98, 0x76, 0x1b, 0xec, 0x14, 0x8e, 0x6b, 0x85, 0xab, 0xd9, 0x25, 0x9f, 0xde, 0x4c, 0x67,
+ 0x8b, 0x8b, 0xeb, 0x6e, 0x73, 0xf4, 0x57, 0x03, 0xba, 0x17, 0xb5, 0x84, 0xac, 0x77, 0xec, 0x0d,
+ 0x1c, 0xc6, 0xb9, 0x7f, 0xe4, 0x73, 0xe7, 0x7c, 0xf8, 0x9c, 0xcf, 0xbc, 0x54, 0xb0, 0x5f, 0x61,
+ 0xa0, 0x51, 0x3d, 0x44, 0x01, 0xfa, 0xf5, 0xec, 0xdd, 0xe6, 0xb0, 0x35, 0xee, 0x9c, 0x7f, 0xb6,
+ 0x6b, 0x25, 0x2f, 0xe3, 0xd7, 0x0f, 0xc2, 0xfb, 0xfa, 0x29, 0x38, 0xfa, 0xb7, 0x09, 0xfd, 0x1d,
+ 0x64, 0xf6, 0x3d, 0xb8, 0xda, 0x08, 0x65, 0x2a, 0x5f, 0x7d, 0x85, 0xda, 0xa8, 0x28, 0x30, 0x74,
+ 0x83, 0x16, 0x3f, 0xa6, 0x7a, 0xe9, 0x2d, 0xcf, 0xab, 0xec, 0x5b, 0x38, 0x46, 0x19, 0xee, 0xd2,
+ 0x35, 0x49, 0x37, 0x40, 0x19, 0x3e, 0x55, 0x7d, 0x05, 0x83, 0x18, 0x55, 0x70, 0x2f, 0xa4, 0xf1,
+ 0xa3, 0xb0, 0xd2, 0xd8, 0x6e, 0x70, 0x38, 0x2b, 0x6a, 0x57, 0x61, 0xa9, 0x98, 0x40, 0x71, 0xa1,
+ 0x2d, 0xc1, 0x1e, 0x09, 0x7a, 0x79, 0xa9, 0xc6, 0xbf, 0x06, 0xa6, 0x50, 0x27, 0x1b, 0x15, 0xa0,
+ 0xae, 0xe8, 0xfb, 0x94, 0xc6, 0xd9, 0x2e, 0x0f, 0x79, 0xc1, 0xe6, 0xbd, 0x52, 0x58, 0xae, 0xf6,
+ 0x23, 0x1c, 0x6d, 0x65, 0xd1, 0xa6, 0x2c, 0x76, 0xa6, 0xba, 0x15, 0xc2, 0x96, 0x6a, 0xf4, 0x77,
+ 0x1b, 0x8e, 0xb6, 0x6c, 0x7f, 0x0d, 0x9d, 0x9a, 0x0d, 0xe4, 0xb4, 0xc3, 0xa1, 0xba, 0x3d, 0x3b,
+ 0x03, 0xa8, 0x6e, 0x4d, 0x8e, 0x3a, 0xdc, 0x29, 0x2f, 0xcb, 0x3e, 0x01, 0x27, 0x8b, 0x4d, 0x63,
+ 0x40, 0xde, 0xb5, 0xf8, 0x21, 0x01, 0x1e, 0x06, 0x76, 0xd2, 0xc2, 0x4d, 0x3e, 0x2e, 0xb6, 0x9e,
+ 0x0d, 0x4a, 0xa7, 0xc0, 0x2c, 0xe5, 0x35, 0x74, 0x74, 0x9a, 0x18, 0xed, 0xd3, 0xf8, 0xd1, 0xbc,
+ 0xb5, 0x38, 0x10, 0xb4, 0xb0, 0x08, 0xed, 0x4f, 0x84, 0x24, 0x45, 0x49, 0xee, 0xb5, 0xb8, 0x43,
+ 0xc8, 0x3c, 0x45, 0xc9, 0x3e, 0x87, 0xee, 0xd6, 0xf3, 0x64, 0xc4, 0xca, 0x3d, 0xa0, 0x43, 0xbe,
+ 0xac, 0xe3, 0x0b, 0xb1, 0x62, 0x3f, 0x80, 0x53, 0xda, 0xea, 0x1e, 0x7e, 0x48, 0x0c, 0x15, 0x9f,
+ 0x7d, 0x01, 0xbd, 0x54, 0x3c, 0xc6, 0x28, 0x8d, 0x9f, 0xa4, 0x74, 0xa1, 0x28, 0x74, 0x9d, 0x61,
+ 0xcb, 0x6e, 0x94, 0x17, 0xe6, 0x84, 0x5f, 0x85, 0xec, 0x2d, 0x80, 0xc2, 0x60, 0xa3, 0x14, 0xda,
+ 0x27, 0x04, 0x68, 0xa7, 0x2f, 0x9f, 0x0b, 0x6a, 0xc2, 0x4b, 0x09, 0xaf, 0xc9, 0x99, 0x00, 0xa6,
+ 0x83, 0x7b, 0x0c, 0x37, 0x6b, 0xf4, 0xf1, 0x8f, 0x00, 0x69, 0x13, 0xb7, 0x43, 0xe9, 0x9f, 0x3f,
+ 0xbb, 0xa8, 0x97, 0x4b, 0xa7, 0x85, 0x92, 0xf7, 0xf4, 0xff, 0xa1, 0xd3, 0xdf, 0x00, 0xaa, 0xcd,
+ 0xd9, 0x18, 0xba, 0x0a, 0x53, 0x14, 0xc6, 0xdf, 0x48, 0x13, 0xad, 0x29, 0xb8, 0x6c, 0x00, 0x5f,
+ 0x64, 0xf8, 0x3b, 0x0b, 0xdb, 0xec, 0x2a, 0x26, 0x3e, 0xa0, 0x7a, 0x24, 0x66, 0xf6, 0xde, 0xe6,
+ 0xcc, 0xa9, 0x85, 0x3d, 0x0c, 0x4e, 0x7f, 0x86, 0xde, 0x93, 0x93, 0xb0, 0x37, 0x00, 0x76, 0x66,
+ 0x7d, 0x25, 0xe4, 0x0a, 0xf3, 0x57, 0x6a, 0x67, 0x20, 0x76, 0x78, 0xb9, 0x25, 0x71, 0xc7, 0x14,
+ 0x3f, 0x47, 0x7f, 0x36, 0xc0, 0x29, 0x93, 0x62, 0x1f, 0x83, 0xed, 0xba, 0xbb, 0xbb, 0xaa, 0x87,
+ 0x0f, 0xe8, 0x3b, 0x6f, 0x60, 0x2a, 0x49, 0x11, 0x63, 0xd9, 0xc0, 0x16, 0x99, 0x89, 0x18, 0xd9,
+ 0x09, 0x1c, 0xa8, 0x24, 0x89, 0xad, 0x30, 0x1b, 0xfd, 0x7d, 0xfb, 0x99, 0x75, 0x36, 0x15, 0x48,
+ 0x96, 0x0d, 0xf9, 0xa1, 0x05, 0x48, 0x75, 0x06, 0x90, 0x0a, 0x65, 0x1e, 0x7d, 0x1d, 0xbd, 0xcf,
+ 0xfe, 0x25, 0xda, 0xdc, 0x21, 0xc4, 0x8b, 0xde, 0xe3, 0xe8, 0x02, 0x9c, 0xf2, 0xd0, 0x76, 0xa1,
+ 0x25, 0xae, 0x22, 0x59, 0x73, 0xf2, 0x90, 0x00, 0xeb, 0xe1, 0x09, 0x1c, 0xd8, 0xc7, 0xab, 0xb0,
+ 0xae, 0xc5, 0xf7, 0x51, 0x86, 0x1e, 0x06, 0xcb, 0x7d, 0xfa, 0x8f, 0xfd, 0xe6, 0xbf, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0x08, 0xf3, 0x9e, 0x1d, 0x7e, 0x07, 0x00, 0x00,
+}
diff --git a/feeds/availability_feed.proto b/feeds/availability_feed.proto
new file mode 100644
index 0000000..e25bd0e
--- /dev/null
+++ b/feeds/availability_feed.proto
@@ -0,0 +1,249 @@
+syntax = "proto3";
+
+package maps.booking.feeds;
+
+message FeedMetadata {
+ enum ProcessingInstruction {
+ // By default we will assume that this feed is an incremental feed.
+ PROCESS_UNKNOWN = 0;
+
+ // This Feed message is one shard of a complete feed. Anything previously
+ // supplied by this partner will be deleted; the contents of this feed
+ // represent the entire state of the world.
+ PROCESS_AS_COMPLETE = 1;
+
+ // This Feed message is one shard of an incremental feed. Existing entities
+ // will be left untouched except as modified in this feed.
+ PROCESS_AS_INCREMENTAL = 2;
+ }
+
+ // Instructs us how to process the feed: either as a shard of a complete feed,
+ // or as a shard of an incremental update.
+ ProcessingInstruction processing_instruction = 1;
+
+ // The current shard and total number of shards for this feed.
+ //
+ // Shard number is assumed to be zero-based.
+ //
+ // There does not need to be any relationship to the file name.
+ //
+ // Shards do not need to be transferred in order, and they may not be
+ // processed in order.
+ int32 shard_number = 2;
+ int32 total_shards = 3;
+
+ // An identifier that must be consistent across all shards in a feed.
+ // This value must be globally unique across each feed type.
+ //
+ // This value ensures that complete feeds spanning multiple shards are
+ // processed together correctly.
+ //
+ // Clients only need to set this value when the processing_instruction is set
+ // to PROCESS_AS_COMPLETE and the feed spans multiple shards (defined by
+ // total_shards).
+ //
+ // Feeds that span multiple shards must set this nonce to the same value.
+ uint64 nonce = 5;
+
+ // The timestamp at which this feed shard was generated.
+ //
+ // In Unix time format (seconds since the epoch).
+ int64 generation_timestamp = 4;
+}
+
+message AvailabilityFeed {
+ FeedMetadata metadata = 1;
+ repeated ServiceAvailability service_availability = 2;
+}
+
+message ServiceAvailability {
+ // If provided, we will consider the Availability entities provided to be a
+ // complete snapshot from [start_timestamp_restrict, end_timestamp_restrict).
+ // That is, all existing availability will be deleted if the following
+ // condition holds true:
+ //
+ // start_timestamp_restrict <= Availability.start_sec &&
+ // Availability.start_sec < end_timestamp_restrict
+ //
+ // If a resource_restrict message is set, the condition is further restricted:
+ //
+ // Availability.resource.staff_id == resource_restrict.staff_id &&
+ // Availability.resource.room_id == resource_restrict.room_id
+ //
+ // These fields are typically used to provide a complete update of
+ // availability in a given time range.
+ //
+ // Setting start_timestamp_restrict while leaving end_timestamp_restrict unset
+ // is interpreted to mean all time beginning at start_timestamp_restrict.
+ //
+ // Setting end_timestamp_restrict while leaving start_timestamp_restrict unset
+ // is interpreted to mean all time up to the end_timestamp_restrict.
+ //
+ // In Unix time format (seconds since the epoch).
+ int64 start_timestamp_restrict = 1;
+ int64 end_timestamp_restrict = 2;
+
+ // If provided, the timestamp restricts will be applied only to the given
+ // merchant or service.
+ //
+ // These fields are typically used to provide complete snapshot of
+ // availability in a given range (defined above) for a specific merchant or
+ // service.
+ //
+ // Leaving these fields unset, or setting these to the empty string or null,
+ // is interpreted to mean that no restrict is intended.
+ string merchant_id_restrict = 3;
+ string service_id_restrict = 4;
+
+ // Setting resources_restrict further restricts the scope of the update to
+ // just this set of resources. All id fields of the resources must match
+ // exactly.
+ Resources resources_restrict = 6;
+
+ repeated Availability availability = 5;
+}
+
+// An availability of the merchant's service, indicating time and number
+// of spots.
+// The availability feed should be a list of this message.
+// Please note that it's up to the partner to call out all the possible
+// availabilities.
+// If a massage therapist is available 9am-12pm, and they provide
+// one-hour massage sessions, the aggregator should provide the feed as
+// availability {start_sec: 9am, duration: 60 minutes, ...}
+// availability {start_sec: 10am, duration: 60 minutes, ...}
+// availability {start_sec: 11am, duration: 60 minutes, ...}
+// instead of
+// availability {start_sec: 9am, duration: 180 minutes, ...}
+//
+message Availability {
+ // An opaque string from an aggregator to identify a merchant.
+ string merchant_id = 1;
+ // An opaque string from aggregator to identify a service of the
+ // merchant.
+ string service_id = 2;
+ // Start time of this availability, using epoch time in seconds.
+ int64 start_sec = 3;
+ // Duration of the service in seconds, e.g. 30 minutes for a chair massage.
+ int64 duration_sec = 4;
+ // Number of total spots and open spots of this availability.
+ // E.g. a Yoga class of 10 spots with 3 booked.
+ // availability {spots_total: 10, spots_open: 7 ...}
+ // E.g. a chair massage session which was already booked.
+ // availability {spots_total: 1, spots_open: 0 ...}
+ //
+ // Note: If sending requests using the availability compression format defined
+ // below, these two fields will be inferred. A Recurrence
+ // implies spots_total=1 and spots_open=1. A ScheduleException implies
+ // spots_total=1 and spots_open=0.
+ int64 spots_total = 5;
+ int64 spots_open = 6;
+ // An optional opaque string to identify this availability slot. If set, it
+ // will be included in the requests that book/update/cancel appointments.
+ string availability_tag = 7;
+
+ // Optional resources used to disambiguate this availability slot from
+ // others when different staff, room, or party_size values are part
+ // of the service.
+ //
+ // E.g. the same Yoga class with two 2 instructors.
+ // availability { resources { staff_id: "1" staff_name: "Amy" }
+ // spots_total: 10 spots_open: 7 }
+ // availability { resources { staff_id: "2" staff_name: "John" }
+ // spots_total: 5 spots_open: 2 }
+ Resources resources = 8;
+
+ // A list of ids referencing the payment options which can be used to pay
+ // for this slot. The actual payment options are defined at the Merchant
+ // level, and can also be shared among multiple Merchants.
+ //
+ // This field overrides any payment_option_ids specified in the service
+ // message. Similarly payment_option_ids specified here do NOT have to be
+ // present in the service message, though must be defined at the
+ // Merchant level.
+ repeated string payment_option_id = 9;
+
+ // Recurrence messages are optional, but allow for a more compact
+ // representation of consistently repeating availability slots. They typically
+ // represent a day's working schedule.
+ // ScheduleException messages are then used to represent booked/unavailable
+ // time ranges within the work day.
+ //
+ // Requirements:
+ // 1. The expansion of availability slots or recurrences must NOT create
+ // identical slots. If the ids, start_sec, duration_sec, and resources
+ // match, slots are considered identical.
+ // 2. Do NOT mix the standard availability format and recurrence within the
+ // slots of a single service. Recurrence benefits merchants/services that
+ // offer appointments. The standard format is geared towards
+ // merchants/services with regularly scheduled classes.
+ message Recurrence {
+ // The inclusive maximum UTC timestamp the availability repeats until.
+ int64 repeat_until_sec = 1;
+ // Defines the time between successive availability slots.
+ //
+ // E.g. An availability with a duration of 20 min, a repeat_every_sec of
+ // 30 min, a start_sec of 9:00am, and a repeat_until_sec of 11:00am will
+ // yield slots at 9-9:20am, 9:30-9:50am, 10-10:20am, 10:30-10:50am,
+ // 11-11:20am.
+ int32 repeat_every_sec = 2;
+ }
+ // The recurrence information for the availability, representing more than one
+ // start time. A recurrence should contain appointments for one working day.
+ Recurrence recurrence = 10;
+
+ // ScheduleException messages are used to represent booked/unavailable time
+ // ranges within the work day. As time slots are booked, the list of
+ // exceptions should grow to reflect the newly unavailable time ranges.
+ // The recurrence itself shouldn't be modified.
+ message ScheduleException {
+ // The time range of the exception.
+ TimeRange time_range = 1;
+ }
+ // When this service cannot be scheduled. To limit the number of
+ // schedule_exception messages consider joining adjacent exceptions.
+ repeated ScheduleException schedule_exception = 11;
+}
+
+// A resource is used to disambiguate availability slots from one another when
+// different staff, room or party_size values are part of the service.
+// Multiple slots for the same service and time interval can co-exist when they
+// have different resources.
+message Resources {
+ // Optional id for a staff member providing the service. This field identifies
+ // the staff member across all merchants, services, and availability records.
+ // It also needs to be stable over time to allow correlation with past
+ // bookings.
+ // This field must be present if staff_name is present.
+ string staff_id = 1;
+
+ // Optional name of a staff member providing the service. This field will be
+ // displayed to users making a booking, and should be human readable, as
+ // opposed to an opaque identifier.
+ // This field must be present if staff_id is present.
+ string staff_name = 2;
+
+ // An optional id for the room the service is located in. This field
+ // identifies the room across all merchants, services, and availability
+ // records. It also needs to be stable over time to allow correlation with
+ // past bookings.
+ // This field must be present if room_name is present.
+ string room_id = 3;
+
+ // An optional name for the room the service is located in. This
+ // field will be displayed to users making a booking, and should be human
+ // readable, as opposed to an opaque identifier.
+ // This field must be present if room_id is present.
+ string room_name = 4;
+
+ // Applicable only for Dining: The party size which can be accommodated
+ // during this time slot. A restaurant can be associated with multiple Slots
+ // for the same time, each specifying a different party_size, if for instance
+ // 2, 3, or 4 people can be seated with a reservation.
+ int32 party_size = 5;
+}
+
+message TimeRange {
+ int64 begin_sec = 1;
+ int64 end_sec = 2;
+}
\ No newline at end of file
diff --git a/testclient/main.go b/testclient/main.go
new file mode 100644
index 0000000..c3f5537
--- /dev/null
+++ b/testclient/main.go
@@ -0,0 +1,314 @@
+/*
+Copyright 2017 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/maps-booking/api"
+ "github.com/maps-booking/utils"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+
+ mpb "github.com/maps-booking/bookingservice"
+ fpb "github.com/maps-booking/feeds"
+)
+
+const logFile = "grpc_test_client_log_"
+
+var (
+ serverAddr = flag.String("server_addr", "example.com:80", "Your grpc server's address in the format of host:port")
+ rpcTimeout = flag.Duration("rpc_timeout", 30*time.Second, "Number of seconds to wait before abandoning request")
+ testSlots = flag.Int("num_test_slots", 10, "Maximum number of slots to test from availability_feed. Slots will be selected randomly")
+ allFlows = flag.Bool("all_tests", false, "Whether to test all endpoints.")
+ healthFlow = flag.Bool("health_check_test", false, "Whether to test the Health endpoint.")
+ checkFlow = flag.Bool("check_availability_test", false, "Whether to test the CheckAvailability endpoint.")
+ bookFlow = flag.Bool("booking_test", false, "Whether to test the CreateBooking endpoint.")
+ listFlow = flag.Bool("list_bookings_test", false, "Whether to test the ListBookings endpoint")
+ statusFlow = flag.Bool("booking_status_test", false, "Whether to test the GetBookingStatus endpoint.")
+ rescheduleFlow = flag.Bool("rescheduling_test", false, "Whether to test the UpdateBooking endpoint.")
+ availabilityFeed = flag.String("availability_feed", "", "Absolute path to availablity feed required for all tests except health. Feeds can be in either json or pb3 format")
+ outputDir = flag.String("output_dir", "", "Absolute path of dir to dump log file.")
+)
+
+type counters struct {
+ TotalSlotsProcessed int
+ HealthCheckSuccess bool
+ CheckAvailabilitySuccess int
+ CheckAvailabilityErrors int
+ CreateBookingSuccess int
+ CreateBookingErrors int
+ ListBookingsSuccess bool
+ GetBookingStatusSuccess int
+ GetBookingStatusErrors int
+ CancelBookingsSuccess int
+ CancelBookingsErrors int
+ ReschedulingSuccess bool
+}
+
+// GenerateBookings creates bookings from an availability feed.
+func GenerateBookings(ctx context.Context, av []*fpb.Availability, stats *counters, c mpb.BookingServiceClient) api.Bookings {
+ log.Println("no previous bookings to use, acquiring new inventory")
+ utils.LogFlow("Generate Fresh Inventory", "Start")
+ defer utils.LogFlow("Generate Fresh Inventory", "End")
+
+ var out api.Bookings
+ totalSlots := len(av)
+ for i, a := range av {
+ if err := api.CheckAvailability(ctx, a, c); err != nil {
+ log.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
+ stats.CheckAvailabilityErrors++
+ continue
+ }
+ stats.CheckAvailabilitySuccess++
+
+ booking, err := api.CreateBooking(ctx, a, c)
+ if err != nil {
+ log.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
+ stats.CreateBookingErrors++
+ continue
+ }
+ out = append(out, booking)
+ stats.CreateBookingSuccess++
+ }
+ return out
+}
+
+func createLogFile() (*os.File, error) {
+ var err error
+ outPath := *outputDir
+ if outPath == "" {
+ outPath, err = os.Getwd()
+ if err != nil {
+ return nil, err
+ }
+ }
+ outFile := filepath.Join(outPath, fmt.Sprintf("%s%s", logFile, time.Now().UTC().Format(time.RFC3339)))
+
+ return os.Create(outFile)
+}
+
+func setTimeout(ctx context.Context) context.Context {
+ tCtx, _ := context.WithTimeout(ctx, *rpcTimeout)
+ return tCtx
+}
+
+func logStats(stats counters) {
+ log.Println("\n************* Begin Stats *************\n")
+ var totalErrors int
+ if *healthFlow || *allFlows {
+ if stats.HealthCheckSuccess {
+ log.Println("HealthCheck Succeeded")
+ } else {
+ totalErrors++
+ log.Println("HealthCheck Failed")
+ }
+ }
+ if *checkFlow || *allFlows {
+ totalErrors += stats.CheckAvailabilityErrors
+ log.Printf("CheckAvailability Errors: %d/%d", stats.CheckAvailabilityErrors, stats.CheckAvailabilityErrors+stats.CheckAvailabilitySuccess)
+ }
+ if *bookFlow || *allFlows {
+ totalErrors += stats.CreateBookingErrors
+ log.Printf("CreateBooking Errors: %d/%d", stats.CreateBookingErrors, stats.CreateBookingErrors+stats.CreateBookingSuccess)
+ }
+ if *listFlow || *allFlows {
+ if stats.ListBookingsSuccess {
+ log.Println("ListBookings Succeeded")
+ } else {
+ totalErrors++
+ log.Println("ListBookings Failed")
+ }
+ }
+ if *statusFlow || *allFlows {
+ totalErrors += stats.GetBookingStatusErrors
+ log.Printf("GetBookingStatus Errors: %d/%d", stats.GetBookingStatusErrors, stats.GetBookingStatusErrors+stats.GetBookingStatusSuccess)
+ }
+ if *rescheduleFlow || *allFlows {
+ if stats.ReschedulingSuccess {
+ log.Println("Rescheduling Succeeded")
+ } else {
+ totalErrors++
+ log.Println("Rescheduling Failed")
+ }
+ }
+
+ log.Println("\n\n\n")
+ if totalErrors == 0 {
+ log.Println("All Tests Pass!")
+ } else {
+ log.Printf("Found %d Errors", totalErrors)
+ }
+
+ log.Println("\n************* End Stats *************\n")
+ os.Exit(0)
+}
+
+func main() {
+ flag.Parse()
+ var stats counters
+
+ // Set up logging before continuing with flows
+ f, err := createLogFile()
+ if err != nil {
+ log.Fatalf("Failed to create log file %v", err)
+ }
+ defer f.Close()
+ log.SetOutput(f)
+
+ opts := append([]grpc.DialOption{}, grpc.WithInsecure())
+ conn, err := grpc.Dial(*serverAddr, opts...)
+ if err != nil {
+ log.Fatalf("fail to dial: %v", err)
+ }
+ defer conn.Close()
+ client := mpb.NewBookingServiceClient(conn)
+
+ ctx := context.Background()
+
+ // HealthCheck Flow
+ if *healthFlow || *allFlows {
+ stats.HealthCheckSuccess = true
+ if err = api.HealthCheck(setTimeout(ctx), conn); err != nil {
+ stats.HealthCheckSuccess = false
+ log.Println(err.Error())
+ }
+ if !*allFlows && !*checkFlow && !*bookFlow &&
+ !*listFlow && !*statusFlow && !*rescheduleFlow {
+ logStats(stats)
+ }
+ }
+
+ // Build availablility records.
+ if *availabilityFeed == "" {
+ log.Fatal("please set availability_feed flag if you wish to test additional flows")
+ }
+ av, err := utils.AvailabilityFrom(*availabilityFeed, *testSlots)
+ if err != nil {
+ log.Fatal(err.Error())
+ }
+ stats.TotalSlotsProcessed += len(av)
+
+ // AvailabilityCheck Flow
+ if *checkFlow || *allFlows {
+ utils.LogFlow("Availability Check", "Start")
+ totalSlots := len(av)
+
+ j := 0
+ for i, a := range av {
+ if err = api.CheckAvailability(setTimeout(ctx), a, client); err != nil {
+ log.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
+ stats.CheckAvailabilityErrors++
+ continue
+ }
+ stats.CheckAvailabilitySuccess++
+ av[j] = a
+ j++
+ }
+ av = av[:j]
+ utils.LogFlow("Availability Check", "End")
+ }
+
+ // CreateBooking Flow.
+ var b []*mpb.Booking
+ if *bookFlow || *allFlows {
+ utils.LogFlow("Booking", "Start")
+ totalSlots := len(av)
+ for i, a := range av {
+ booking, err := api.CreateBooking(setTimeout(ctx), a, client)
+ if err != nil {
+ log.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
+ stats.CreateBookingErrors++
+ continue
+ }
+ b = append(b, booking)
+ stats.CreateBookingSuccess++
+ }
+ utils.LogFlow("Booking", "End")
+ }
+
+ // ListBookings Flow
+ if *listFlow || *allFlows {
+ if len(b) == 0 {
+ b = GenerateBookings(setTimeout(ctx), av, &stats, client)
+ }
+ utils.LogFlow("List Bookings", "Start")
+ b, err = api.ListBookings(setTimeout(ctx), b, client)
+ stats.ListBookingsSuccess = true
+ if err != nil {
+ stats.ListBookingsSuccess = false
+ log.Println(err.Error())
+ }
+ utils.LogFlow("List Bookings", "End")
+ }
+
+ // GetBookingStatus Flow
+ if *statusFlow || *allFlows {
+ if len(b) == 0 {
+ b = GenerateBookings(setTimeout(ctx), av, &stats, client)
+ }
+
+ utils.LogFlow("BookingStatus", "Start")
+ totalBookings := len(b)
+
+ j := 0
+ for i, booking := range b {
+ if err = api.GetBookingStatus(setTimeout(ctx), booking, client); err != nil {
+ log.Printf("%s. abandoning booking %d/%d", err.Error(), i, totalBookings)
+ stats.GetBookingStatusErrors++
+ continue
+ }
+ stats.GetBookingStatusSuccess++
+ b[j] = booking
+ j++
+ }
+ b = b[:j]
+ utils.LogFlow("BookingStatus", "End")
+ }
+
+ // CancelBooking Flow
+ if len(b) > 0 {
+ utils.LogFlow("Cancel Booking", "Start")
+ for i, booking := range b {
+ if err = api.CancelBooking(setTimeout(ctx), booking, client); err != nil {
+ log.Printf("%s. abandoning booking %d/%d", err.Error(), i, len(b))
+ stats.CancelBookingsErrors++
+ continue
+ }
+ stats.CancelBookingsSuccess++
+ }
+ utils.LogFlow("Cancel Booking", "End")
+ }
+
+ // Rescheduling is nuanced and can be isolated
+ // from the rest of the tests.
+ if *rescheduleFlow || *allFlows {
+ utils.LogFlow("Rescheduling", "Start")
+ stats.ReschedulingSuccess = true
+ if err = api.Rescheduling(setTimeout(ctx), av, client); err != nil {
+ log.Println(err.Error())
+ stats.ReschedulingSuccess = false
+ }
+ utils.LogFlow("Rescheduling", "End")
+ }
+
+ logStats(stats)
+}
diff --git a/utils/utils.go b/utils/utils.go
new file mode 100644
index 0000000..270b539
--- /dev/null
+++ b/utils/utils.go
@@ -0,0 +1,158 @@
+/*
+Copyright 2017 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package utils contains common BookingService based helper functions.
+package utils
+
+import (
+ "crypto/md5"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes"
+ "github.com/google/go-cmp/cmp"
+
+ mpb "github.com/maps-booking/bookingservice"
+ fpb "github.com/maps-booking/feeds"
+)
+
+// SlotKey is a struct representing a unique service.
+type SlotKey struct {
+ MerchantID string
+ ServiceID string
+ StaffID string
+ RoomID string
+}
+
+// LogFlow is a convenience function for logging common flows..
+func LogFlow(f string, status string) {
+ log.Println(strings.Join([]string{"\n##########\n", status, f, "Flow", "\n##########"}, " "))
+}
+
+// AvailabilityFrom parses the file specified in availabilityFeed, returning a random permutation of availability data, maximum entries specified in testSlots
+func AvailabilityFrom(availabilityFeed string, testSlots int) ([]*fpb.Availability, error) {
+ LogFlow("Parse Input Feed", "Start")
+ defer LogFlow("Parse Input Feed", "End")
+
+ var feed fpb.AvailabilityFeed
+ content, err := ioutil.ReadFile(availabilityFeed)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read input file: %v", err)
+ }
+ if path.Ext(availabilityFeed) == ".json" {
+ if err := jsonpb.UnmarshalString(string(content), &feed); err != nil {
+ return nil, fmt.Errorf("unable to parse feed as json: %v", err)
+ }
+ }
+ if path.Ext(availabilityFeed) == ".pb3" {
+ if err := proto.Unmarshal(content, &feed); err != nil {
+ return nil, fmt.Errorf("unable to parse feed as pb3: %v", err)
+ }
+ }
+
+ var finalAvailability []*fpb.Availability
+ var rawAvailability []*fpb.Availability
+ for _, sa := range feed.GetServiceAvailability() {
+ rawAvailability = append(rawAvailability, sa.GetAvailability()...)
+ }
+ if len(rawAvailability) == 0 || testSlots == 0 {
+ return finalAvailability, errors.New("no valid availability in feed, exiting workflows")
+ }
+ if len(rawAvailability) <= testSlots {
+ finalAvailability = rawAvailability
+ } else {
+ nums := rand.Perm(len(rawAvailability))[0:testSlots]
+ for _, n := range nums {
+ finalAvailability = append(finalAvailability, rawAvailability[n])
+ }
+ }
+ log.Printf("Selected %d slots out of a possible %d", len(finalAvailability), len(rawAvailability))
+ return finalAvailability, nil
+}
+
+// ValidateBooking performs granular comparisons between all got and want Bookings.
+func ValidateBooking(got *mpb.Booking, want *mpb.Booking) error {
+ if got.GetBookingId() == "" {
+ return errors.New("booking_id is empty")
+ }
+ if diff := cmp.Diff(got.GetSlot(), want.GetSlot(), cmp.Comparer(proto.Equal)); diff != "" {
+ return fmt.Errorf("slots differ (-got +want)\n%s", diff)
+ }
+ // UserId is the only required field for the partner to return.
+ if diff := cmp.Diff(got.GetUserInformation().GetUserId(), want.GetUserInformation().GetUserId()); diff != "" {
+ return fmt.Errorf("users differ (-got +want)\n%s", diff)
+ }
+ if diff := cmp.Diff(got.GetPaymentInformation(), want.GetPaymentInformation(), cmp.Comparer(proto.Equal)); diff != "" {
+ return fmt.Errorf("payment information differs (-got +want)\n%s", diff)
+ }
+ if diff := cmp.Diff(got.GetStatus(), mpb.BookingStatus_CONFIRMED); diff != "" {
+ return fmt.Errorf("status differs (-got +want)\n%s", diff)
+ }
+ return nil
+}
+
+// BuildIdempotencyToken creates a unique token based on the slot and user attempting to book the slot.
+func BuildIdempotencyToken(a *fpb.Availability, u string) string {
+ r := a.GetResources()
+ parts := []string{a.GetMerchantId(), a.GetServiceId(), strconv.FormatInt(a.GetStartSec(), 10), strconv.FormatInt(a.GetDurationSec(), 10), r.GetStaffId(), r.GetRoomId(), u}
+ key := strings.Join(parts, "")
+ return fmt.Sprintf("%x", md5.Sum([]byte(key)))
+}
+
+// BuildSlotFrom creates a bookingservice slot from an feed availability record.
+func BuildSlotFrom(a *fpb.Availability) (*mpb.Slot, error) {
+ startTime, err := ptypes.TimestampProto(time.Unix(a.GetStartSec(), 0))
+ if err != nil {
+ return nil, err
+ }
+ r := a.GetResources()
+ return &mpb.Slot{
+ MerchantId: a.GetMerchantId(),
+ ServiceId: a.GetServiceId(),
+ StartTime: startTime,
+ Duration: ptypes.DurationProto(time.Duration(a.GetDurationSec()) * time.Second),
+ AvailabilityTag: a.GetAvailabilityTag(),
+ Resources: &mpb.Resources{
+ StaffId: r.GetStaffId(),
+ RoomId: r.GetRoomId(),
+ PartySize: r.GetPartySize(),
+ },
+ }, nil
+}
+
+// BuildMerchantServiceMap creates a key value pair of unique services to all of their availability slots.
+func BuildMerchantServiceMap(av []*fpb.Availability) map[SlotKey][]*fpb.Availability {
+ m := make(map[SlotKey][]*fpb.Availability)
+ for _, a := range av {
+ key := SlotKey{
+ MerchantID: a.GetMerchantId(),
+ ServiceID: a.GetServiceId(),
+ StaffID: a.GetResources().GetStaffId(),
+ RoomID: a.GetResources().GetRoomId(),
+ }
+ m[key] = append(m[key], a)
+ }
+ return m
+}