mindbody-api icon indicating copy to clipboard operation
mindbody-api copied to clipboard

Error message not in response.message

Open jharbert opened this issue 10 years ago • 5 comments

Wondering if you have thoughts on this.

If a client is already booked at some time, and you attempt to create another appointment with them at the time in which they are already booked, the request fails but there is no message in the response:

[181] pry(main)> response.message
=> nil

However there is an error in the response body:

[182] pry(main)> response.body[:add_or_update_appointments_response][:add_or_update_appointments_result][:appointments][:messages] 
=> "100015707 Already booked - Client is already booked at this time"

Here's the full response:

[178] pry(main)> response
=> #<MindBody::Services::Response:0x007f808e7639d0
 @api_status=#<MindBody::APIStatus::Success:0x007f80970f1120 @message=nil>,
 @current_page_index="0",
 @error_code="201",
 @response=
  #<Savon::Response:0x007f808e763ef8
   @globals=
    #<Savon::GlobalOptions:0x007f8090810f70
     @option_type=:global,
     @options=
      {:encoding=>"UTF-8",
       :soap_version=>1,
       :namespaces=>{},
       :logger=>
        #<Logger:0x007f8090810de0
         @default_formatter=#<Logger::Formatter:0x007f8090810db8 @datetime_format=nil>,
         @formatter=nil,
         @level=0,
         @logdev=#<Logger::LogDevice:0x007f8090810d68 @dev=#<IO:<STDOUT>>, @filename=nil, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x007f8090810d40 @mon_count=0, @mon_mutex=#<Mutex:0x007f8090810cf0>, @mon_owner=nil>, @shift_age=nil, @shift_size=nil>,
         @progname=nil>,
       :log=>false,
       :filters=>[],
       :pretty_print_xml=>false,
       :raise_errors=>true,
       :strip_namespaces=>true,
       :convert_response_tags_to=>#<Proc:0x007f8090810c28@/Users/jharbert/.rvm/gems/ruby-2.2.1/gems/savon-2.11.0/lib/savon/options.rb:85 (lambda)>,
       :convert_attributes_to=>#<Proc:0x007f8090810c00@/Users/jharbert/.rvm/gems/ruby-2.2.1/gems/savon-2.11.0/lib/savon/options.rb:86 (lambda)>,
       :multipart=>false,
       :adapter=>nil,
       :use_wsa_headers=>false,
       :no_message_tag=>false,
       :follow_redirects=>false,
       :unwrap=>false,
       :wsdl=>"/Users/jharbert/.rvm/gems/ruby-2.2.1/bundler/gems/mindbody-api-203fd1bfda78/wsdl/AppointmentService.wsdl",
       :open_timeout=>60,
       :read_timeout=>60,
       :endpoint=>#<URI::HTTPS https://api.mindbodyonline.com/0_5/AppointmentService.asmx>}>,
   @hash=
    {:envelope=>
      {:body=>
        {:add_or_update_appointments_response=>
          {:add_or_update_appointments_result=>
            {:status=>"Success",
             :error_code=>"201",
             :xml_detail=>"Full",
             :result_count=>"0",
             :current_page_index=>"0",
             :total_page_count=>"0",
             :appointments=>{:messages=>"100015707 Already booked - Client is already booked at this time", :error_code=>"504", :duration=>nil, :action=>"Failed"}},
           :@xmlns=>"http://clients.mindbodyonline.com/api/0_5"}},
       :"@xmlns:soap"=>"http://schemas.xmlsoap.org/soap/envelope/",
       :"@xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
       :"@xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema"}},
   @http=
    #<HTTPI::Response:0x007f80961405f0
     @body=
      "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><AddOrUpdateAppointmentsResponse xmlns=\"http://clients.mindbodyonline.com/api/0_5\"><AddOrUpdateAppointmentsResult><Status>Success</Status><ErrorCode>201</ErrorCode><XMLDetail>Full</XMLDetail><ResultCount>0</ResultCount><CurrentPageIndex>0</CurrentPageIndex><TotalPageCount>0</TotalPageCount><Appointments><Appointment><Messages><string>100015707 Already booked - Client is already booked at this time</string></Messages><ErrorCode>504</ErrorCode><Duration xsi:nil=\"true\" /><Action>Failed</Action></Appointment></Appointments></AddOrUpdateAppointmentsResult></AddOrUpdateAppointmentsResponse></soap:Body></soap:Envelope>",
     @code=200,
     @headers=
      {"cache-control"=>"private, max-age=0",
       "content-type"=>"text/xml; charset=utf-8",
       "x-aspnet-version"=>"4.0.30319",
       "x-powered-by"=>"ASP.NET",
       "p3p"=>"CAO DSP COR CUR TAIa OUR NOR UNI STA",
       "content-length"=>"837",
       "date"=>"Fri, 12 Jun 2015 20:23:56 GMT",
       "connection"=>"keep-alive",
       "access-control-max-age"=>"86400",
       "access-control-allow-headers"=>"Accept, SiteId, Authorization, Content-Type, Origin",
       "access-control-allow-methods"=>"GET, POST, PUT, DELETE, OPTIONS",
       "access-control-allow-credentials"=>"true",
       "access-control-allow-origin"=>""},
     @raw_body=
      "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><AddOrUpdateAppointmentsResponse xmlns=\"http://clients.mindbodyonline.com/api/0_5\"><AddOrUpdateAppointmentsResult><Status>Success</Status><ErrorCode>201</ErrorCode><XMLDetail>Full</XMLDetail><ResultCount>0</ResultCount><CurrentPageIndex>0</CurrentPageIndex><TotalPageCount>0</TotalPageCount><Appointments><Appointment><Messages><string>100015707 Already booked - Client is already booked at this time</string></Messages><ErrorCode>504</ErrorCode><Duration xsi:nil=\"true\" /><Action>Failed</Action></Appointment></Appointments></AddOrUpdateAppointmentsResult></AddOrUpdateAppointmentsResponse></soap:Body></soap:Envelope>">,
   @locals=
    #<Savon::LocalOptions:0x007f80981c6978
     @option_type=:local,
     @options=
      {:advanced_typecasting=>true,
       :response_parser=>:nokogiri,
       :multipart=>false,
       :message=>
        {"Request"=>
          {"SourceCredentials"=>{"SourceName"=>"xxx", "Password"=>"xxx", "SiteIDs"=>{"int"=>["-99"]}},
           "Appointments"=>{"Appointment"=>{"StartDateTime"=>"2015-06-15T12:00:00-04:00", "Location"=>{"ID"=>1}, "Staff"=>{"ID"=>"100000237"}, "Client"=>{"ID"=>100015707}, "SessionType"=>{"ID"=>23}, "Notes"=>"abc"}}}},
       :soap_action=>"http://clients.mindbodyonline.com/api/0_5/AddOrUpdateAppointments"}>,
   @nori=
    #<Nori:0x007f808e7637c8
     @options=
      {:strip_namespaces=>true,
       :delete_namespace_attributes=>false,
       :convert_tags_to=>#<Proc:0x007f8090810c28@/Users/jharbert/.rvm/gems/ruby-2.2.1/gems/savon-2.11.0/lib/savon/options.rb:85 (lambda)>,
       :convert_attributes_to=>#<Proc:0x007f8090810c00@/Users/jharbert/.rvm/gems/ruby-2.2.1/gems/savon-2.11.0/lib/savon/options.rb:86 (lambda)>,
       :empty_tag_value=>nil,
       :advanced_typecasting=>true,
       :convert_dashes_to_underscores=>true,
       :parser=>:nokogiri}>>,
 @result=
  {:appointments=>
    #<MindBody::Models::Appointment:0x007f808e672530
     @client=nil,
     @client_service=nil,
     @duration=nil,
     @end_date_time=nil,
     @first_appointment=nil,
     @gender_preference=nil,
     @id=nil,
     @location=nil,
     @notes=nil,
     @program=nil,
     @resources=[],
     @session_type=nil,
     @staff=nil,
     @staff_requested=nil,
     @start_date_time=nil,
     @status=nil>},
 @result_count="0",
 @status="Success",
 @total_page_count="0",
 @xml_detail="Full">

jharbert avatar Jun 12 '15 20:06 jharbert

@jharbert Yes, I see something like that, too. And I'm oddly getting that exact same error on a call to cancel a class. This is an example failure response I've gotten when calling remove_clients_from_classes:

status: "FailedAction"
error_code: "200"
message: "An action has failed. Please see object message for details."
xml_detail: "Full"
result_count: "0"
current_page_index: "0"
total_page_count: "0"
classes: {
  class_schedule_id: "285"
  clients: {
    messages: "100003091 Already booked ClassID: 14910 - Client is already booked at this time"
    ...

I have no idea why I see that message when I cancel a class -- seems weird. But anyway, yes, I have to dig down into [:classes][:clients][:messages] to retrieve the message for error reporting, though not into the response body.

stevehanson avatar Mar 01 '16 15:03 stevehanson

Is MindBody returning that message at the top level of the response? response.message will pull from there. The odd messages are coming from MindBody (unless this code is pulling the wrong message out). I'll see if I can take a look in the new few days.

wingrunr21 avatar Mar 01 '16 15:03 wingrunr21

@wingrunr21 here is the XML response. There was a generic message in the top-level response.message and then the more descriptive message under classes > clients:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <RemoveClientsFromClassesResponse xmlns="http://clients.mindbodyonline.com/api/0_5">
      <RemoveClientsFromClassesResult>
        <Status>FailedAction</Status>
        <ErrorCode>200</ErrorCode>
        <Message>An action has failed. Please see object message for details.</Message>
        <XMLDetail>Full</XMLDetail>
        <ResultCount>0</ResultCount>
        <CurrentPageIndex>0</CurrentPageIndex>
        <TotalPageCount>0</TotalPageCount>
        <Classes>
          <Class>
            <ClassScheduleID>285</ClassScheduleID>
            <Clients>
              <Client>
                <Messages>
                  <string>100003091 Already booked ClassID: 14910 - Client is already booked at this time</string>
                </Messages>
                <Username>XXXXXXXXXXXXXXXX</Username>
                <MobileProvider xsi:nil="true" />
                <AppointmentGenderPreference>None</AppointmentGenderPreference>
                <IsCompany>false</IsCompany>
                <LiabilityRelease>false</LiabilityRelease>
                <PromotionalEmailOptIn>true</PromotionalEmailOptIn>
                <CreationDate>2016-01-31T20:15:05.98</CreationDate>
                <Liability>
                  <IsReleased>false</IsReleased>
                  <AgreementDate xsi:nil="true" />
                  <ReleasedBy xsi:nil="true" />
                </Liability>
                <Action>Failed</Action>
                <ID>100003091</ID>
                <FirstName>XXXX</FirstName>
                <LastName>XXXX</LastName>
                <Email>XXXX</Email>
                <EmailOptIn>false</EmailOptIn>
                <AddressLine1>XXXX</AddressLine1>
                <City>Dallas</City>
                <State>TX</State>
                <PostalCode>75230</PostalCode>
                <Country>US</Country>
                <MobilePhone>XXXX</MobilePhone>
                <HomePhone>XXXX</HomePhone>
                <BirthDate>XXXX</BirthDate>
                <FirstAppointmentDate xsi:nil="true" />
                <ReferredBy>XXXX</ReferredBy>
                <IsProspect>false</IsProspect>
                <ContactMethod>1</ContactMethod>
              </Client>
            </Clients>
            <Location>
              ...
            </Location>
            <MaxCapacity xsi:nil="true" />
            <WebCapacity xsi:nil="true" />
            <TotalBooked xsi:nil="true" />
            <TotalBookedWaitlist xsi:nil="true" />
            <WebBooked xsi:nil="true" />
            <SemesterID xsi:nil="true" />
            <IsCanceled>false</IsCanceled>
            <Substitute>false</Substitute>
            <Active>true</Active>
            <IsWaitlistAvailable>false</IsWaitlistAvailable>
            <IsEnrolled>false</IsEnrolled>
            <HideCancel>false</HideCancel>
            <ID>14910</ID>
            <IsAvailable>true</IsAvailable>
            <StartDateTime>2016-03-12T18:30:00</StartDateTime>
            <EndDateTime>2016-03-12T21:30:00</EndDateTime>
            <ClassDescription>
              ...
            </ClassDescription>
            <Staff>
              ...
            </Staff>
          </Class>
        </Classes>
      </RemoveClientsFromClassesResult>
    </RemoveClientsFromClassesResponse>
  </soap:Body>
</soap:Envelope>

stevehanson avatar Mar 01 '16 16:03 stevehanson

It seems like, in my case, you're doing the right thing by passing me the top level message. If I have a complaint, it'd be directed toward MindBody burying their error message.

stevehanson avatar Mar 01 '16 16:03 stevehanson

Yes, that is MindBody being helpful as usual. I'd follow up with MindBody (although FYI they are not very receptive to API feedback. I've been fighting for timezones in their timestamps forever now).

So as this is not a code issue, would there be a preferable API? message cannot be modified as that is used for all API calls. It may be possible to expose buried messages in a nicer way. It would likely require a recursive search to extract all messages. I'm not sure that buys anyone anything as there'd still have to be some kind of hierarchy so that you could know which object has which message.

wingrunr21 avatar Mar 01 '16 16:03 wingrunr21