Archive

Author Archive

SWS MakeReservation Method

Creates a rental, reservation or quote. Also converts a quote or reservation into a rental using the quote ID from the initial MakeReservation call.

A rental item can be put on hold by calling the UpdateUnitStatus SWS method, before calling this method, to ensure nobody else takes the rental item while setting up the reservation. If the customer declines the reservation/rental, you will need to call UpdateUnitStatus again, to make the unit available.

The progression of reservations to rental is Quote > SoftReservation > HardReservation > Rental. If you set up a quote, it can be updated to any of the following types of reservations. If you set up a hard reservation it can only be cancelled or set to a rental, it cannot go back in the progression.

Settings for the different types of quotes:

  • Quote – QuoteType = QuoteOnly, RentNow = False
    • Does not reserve a unit at all. If a customer wants to rent and no units are available, they will have to wait for a unit. No reservation fee can be applied as no rental is reserved.
  • Soft Reservation – QuoteType = SoftReservation, RentNow = False
    • Reserves a unit of the type requested. This does not guarantee a specific unit. A reservation fee cannot be applied as there is not a specific unit being held.
  • Hard Reservation – QuoteType=HardReservation, RentNow = False
    • Reserves a specific unit. A reservation fee may be applicable based on the site rules. If they have assigned a reservation fee, the total to hold the reservation can be found using the GetTotalDue method.
  • Rental – QuoteType = QuoteOnly, RentNow = True
    • The first payment of a rental is always required in full or, if the site allows it, can be deferred at the site. A deferral cannot be done through the API. If a move in payment is not taken, nightly processing will set the rental to abandoned and remove the rental from the customer’s account.

To convert a quote or reservation to a rental, use the quote ID from the initial call. Run the quote ID through MakeReservations again, choosing “True” for RentNow. This will put the unit into the “In-Process” status. Once a payment is completed, the quote will become a rental.

To prevent duplicate use of a unit, we use the version number.

For a work flow of what is required for a new reservation/rental, see the Workflow for Creating a Reservation or Rental. (Note: A move-in will always require a payment even if it’s a $0 cash payment, otherwise, the rental is cancelled by the system during our nightly processing.)

Parameters

Name DataType Is Required
AcctID Long Required
Description The account’s ID number. This is returned when you use the CreateNewAccount method or can be retrieved with the SearchBy method.
Contacts RentalContact Required
Description A collection of contact data to tie to the reservation/quote. Two contacts may be required if the site rules require it.
InquirySource Integer Optional
Description The available inquiry source for how customers heard about the site. This takes advantage of the Store Lookups feature in Org Admin. This can be found using the eInquirySource method.
Pcds TRAN_QUOTE_PCD_DETAIL Optional
Description A collection of promotions and discounts (PCD) to tie to the reservation. This is returned, if requested, in any of the GetSiteUnitData methods or can be retrieved with the GetAvailableDiscounts method.
Price Decimal Optional
Description Overrides the current rent rate of the unit. This will use the existing rent rate if left undefined.
QuoteExpiration DateTime Optional
Description The date the quote/reservation is no longer available. If passed in, it will override the rules in Store.
QuoteID Long Optional
Description The quote’s ID number. If this is left blank, then it will create a new quote with the information passed in. If this is entered it will update an existing quote/reservation.
QuoteStartDate DateTime Optional
Description The date that the quote record was created.
QuoteType Quote_Types Required
Description The quote’s type.
Available values:

  • QuoteOnly
  • SoftReservation
  • HardReservation
RentNow Boolean Required
Description Indicates that you want to set the unit as a rental (“True”) or as a quote or reservation (“False”).
SiteID Long Required
Description The site’s ID number. This can be found using the GetSiteList method.
UnitID Long Required
Description The unit’s ID number. This is returned when you use any of the GetSiteUnitData
calls and is maintained through rentals.
Version Decimal Optional
Description The unit’s version number which serves to prevent duplicate use of the unit.

Returned Parameters

Name DataType
QuoteID Long
Description The quote’s ID number.
RentalID Long
Description The rental item’s ID number. No rental ID is returned when a quote is created, this is only returned with reservations and rentals.

Example

As with every method we need to pass in credentials. We do this with the LookupUser request object.

We’ll assume you’ve got a web reference, let’s name it SWS, in your Visual Studio project.  At this point we need to our objects.  We’ll need the standard service object, a MakeReservation request object and a MakeReservation response object.  As part of the request object we also one or more RentalContact objects. We can define and create those like this:

// Create a request and response objects
SWS.WSSoapClient service = new SWS.WSSoapClient();
SWS.MakeReservation_Request request = new SWS.MakeReservation_Request();
SWS.MakeReservation_Response response;

SWS.RentalContact conRequest = new SWS.RentalContact();

Prior to setting the data in the MakeReservation Request object we’ll need to define our rental contact. It can take in an array of contacts but only one is required, unless specified otherwise by the site rules.  To establish a contact we need to define the ContactId, AddressId and PhoneID. These are created using the AddNewContact, AddNewAddress, and AddNewPhone methods. Please see the workflow mentioned above for additional information on account and contact creation.

// RentalContact object
conRequest.ContactId = 123456;
conRequest.AddressId = 123456;
conRequest.PhoneId = 123456;
conRequest.PrimaryFlag = true;

Here’s my sample code of the Request object.

// MakeReservation Request
request.SiteID = 123456;
request.AcctID = 123456;
request.UnitID = 123456;
request.Version = 5;
request.QuoteType = SWS.Quote_Types.QuoteOnly;
request.RentNow = false;
request.Price = 50m;
request.Contacts = new SWS.RentalContact[] { conRequest };

Finally we can call the method and pass across the login object and the request object to perform our reservation. It’s a good
idea to do this in a Try Catch block.

// Call the method that will load the response object
 try
{
  response = service.MakeReservation(user_request, request);
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);
}

Note that if something goes wrong the service will respond with an exception. You’ll want to take a look at that message returned in that exception so it can be debugged.

Each organization has the ability to limit when a reservation can be made.
These limiting factors can be found at GetSiteRules Info.

For a full list of methods see SWS Methods.

Using SWS on iPhone/iPad – Part 2 Parsing the XML response

SAX vs. DOM

As we begin, I want to explain the most important difference between XML parsers, whether the parser is a SAX or a DOM parser.
  • A SAX parser is one where your code is notified as the parser walks through the XML tree, and you are responsible for keeping track of state and constructing any objects you might want to keep track of the data as the parser marches through.
  • A DOM parser reads the entire document and builds up an in-memory representation that you can query for different elements. Often, you can even construct XPath queries to pull out particular pieces.
Alright, now let’s discuss some of the libraries!

XML Parsers for the iPhone

In the iphone SDK the two choices are:
  • NSXMLParser is a SAX parser included by default with the iPhone SDK. It’s written in Objective-C and is quite straightforward to use, but perhaps not quite as easy as the DOM model.  It is the fastest parser in terms of parsing xml from start to finish.
  • libxml2 is an Open Source library that is included by default with the iPhone SDK. It is a C-based API, so is a bit more work to use than NSXML. The library supports both DOM and SAX processing. The libxml2 SAX processor is especially cool, as it has a unique feature of being able to parse the data as it’s being read. For example, you could be reading a large XML document from the network and displaying data that you’re reading for it to the user while you’re still downloading. Therefore, while this parser is slower than NSXMLParser from start to finish, the user experience is improved in the case of large xml documents.
If you’re wondering about memory usage, it’s a wash if you’re comparing SAX parsers.  If you implement DOM parser you will incur a greater memory usage.  There are other 3rd party libraries
which provide other DOM capabilities such as XPath functionality.  If you get into parsing complex xml structures these may be a good consideration. For our purposes we will use NSXMLParser.  I’ve found it to be the path of least resistance and it really wants to be friendly so we’ll play along.

The XML

As we are calling the site list method we will be getting back xml that follows the format documented at: http://host05slc.centershift.com/iService/iService1.asmx?op=GetSiteList
Here’s the response format:
xml version=”1.0″ encoding=”utf-8″?>
<soap:Body>
<GetSiteListResponse xmlns=”http://centershift.com/”&gt;

<GetSiteListResult>

<Facility>

<SiteName>string</SiteName>

<SiteId>string

<DistanceTo>string</DistanceTo>

</Facility>

<Facility>

<SiteName>string</SiteName>

<SiteId>string</SiteId>

<DistanceTo>string</DistanceTo>

</Facility>

</GetSiteListResult>

</GetSiteListResponse>

</soap:Body>
</soap:Envelope>
We want to parse through all the ‘Facility’ elements and grab the SiteName and SiteId to display them in a list.  To launch the parsing process we will want to add some code to the connectionDidFinishLoading method.
– (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Manipulate data here and release Data and Connection
NSLog(@”Succeeded!
Received %d bytes of data\n”,[webData length]);
NSString *theXml = [[NSString alloc]initWithBytes:[webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
[theXml release];
// Parse received xml from web service
// XMLParse declared in the header
myParser= [[NSXMLParser alloc] initWithData: webData];
[myParser setDelegate:self];
// Depending on the XML document you’re parsing, you may want to enable these features of NSXMLParser.
[myParser setShouldProcessNamespaces:NO];
[myParser setShouldReportNamespacePrefixes:NO];
[myParser setShouldResolveExternalEntities:NO];
[myParser parse];
// release the connection, and the data object
[connection release];
[webData release];
}
Now it’s time to delve into the parser object methods.  First let’s deal with handling errors thrown during the parse process with the parseErrorOccurred method.
– (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSString * errorString = [NSString stringWithFormat:@”Unable to download feed from web service (Error code %i )”, [parseError code]];
NSLog(@”error parsing XML: %@”, errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@”Error loading content” message:errorString delegate:self
cancelButtonTitle:@”OK” otherButtonTitles:nil];
[errorAlert show];
}
At this point in the didStartElement method we will do our work to clear out the item cache and initialize a new one when we find the start of the ‘Facility’ element.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName

 

namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict

 

{
currentElement=[elementName copy];
if
([elementName isEqualToString:@”Facility”])
{
[currentSite release];
currentSite = [[Site alloc] init];
}}
As the parser parses the Facility element we will append the strings to the two items in our ‘currentSite’ object, namely ‘siteName’ and ‘siteId’.
– (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// save the characters for the current item…
if
([currentElement isEqualToString:@”SiteName”])
{
currentSite.siteName = [currentSite.siteName stringByAppendingString:string];
}
else if
([currentElement isEqualToString:@”SiteId”])
{
currentSite.siteId = [currentSite.siteId stringByAppendingString:string];
}}
The next method lets us deal with whatever we want to do once the parser finds the end element.  In this case we will add the object ‘currentSite’ to our collection or array of objects  ‘allSites’.
– (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if
([elementName isEqualToString:@”Facility”])
{
// save values to an item, then store that item into the array…
[allSites addObject:currentSite];
}}
Lastly, when the parser reaches the end of the xml document we’ll want to perform whatever garbage collection we need to do.  Also, here I allocate a new array of the Sitelist and  load the data into a table which is displayed in the view.  It’s also a good point to stop the animation of the busy Signal so the user has a good experience.
– (void)parserDidEndDocument:(NSXMLParser *)parser
{
// set mySites to allSites
[mySites release];
mySites = [[NSArray alloc] initWithArray:allSites];
[sitelistTable reloadData];
// Stop Indicator
[busySignal stopAnimating];
}

Using SWS web services on iPhone/iPad – Part 1 Calling the service

iPhone/iPad Apps

In today’s marketplace users are looking for applications that extend their functionality to their iPhone/iPad device.  Building business applications on the iPhone/iPad that communicating with web services that provides that functionality in the cloud is a great way to embrace this build forward thinking revolution.  However, consuming web services in an iPhone application is not for the faint-of-heart. Unlike other development tools (such as Microsoft Visual Studio), Xcode does not have built-in tools that make consuming web services easy. Everything must be done by hand and you need to know how to form the relevant XML (SOAP) messages to send to the web services and then parse the returning XML result.

Using SOAP 1.1

One way to consume this web service is to use SOAP (Simple Object Access Protocol). When using SOAP, you use the HTTP POST (or securely over HTTPS) method to send a request to the web service.  In a browser open the url: http://host05slc.centershift.com/iService/iService1.asmx The following is a sample SOAP 1.1 request and response.
The placeholders shown need to be replaced with actual values.
POST /iService/iService1.asmx HTTP/1.1
Host: host05slc.centershift.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://centershift.com/GetSiteList"

      string</UserName>
      <Password>string
    <!--GetSiteList>

To get a request to work from within xCode/Objective C

-(void)GetSiteList{
NSString *soapMessage = [NSString stringWithFormat:@
“xml version=\”1.0\” encoding=\”utf-8\”?>\n”
“<soap:Body>\n”
“xmlns=\”http://centershift.com/\”>\n”
“<UserName>%@</UserName>\n”
“<Password>%@</Password>\n”
“</GetSiteList>\n”
“</soap:Body>\n”
“</soap:Envelope>\n”, [[NSUserDefaults standardUserDefaults] stringForKey:@”MyCSUserName”], [[NSUserDefaults standardUserDefaults] stringForKey:@”MyCSPassword”] ];
// Web service I setup to do this test application.
NSURL *url = [NSURL URLWithString:@”http://host05slc.centershift.com/iService/iService1.asmx“];
// Setup the web request with the url we created
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
// need length of the soap xml for the header in the html file

NSString *msgLength = [NSString stringWithFormat:@”%d”, [soapMessage length]];
// add our htm headers which is a must for a WebService
[theRequest addValue:@”text/xml; charset=utf-8″ forHTTPHeaderField:@”Content-Type”];
[theRequest addValue:@”http://centershift.com/GetSiteList&#8221; forHTTPHeaderField:@”SOAPAction”];
[theRequest addValue:msgLength forHTTPHeaderField:@”Content-Length”];
//We are doing a HTML POST
[theRequest setHTTPMethod:@”POST”];
// set the HTML Body, which is the XML Soap message we created above. Needs to be UTF8 encoding
// Needs to be of type Data [theRequest setHTTPBody: [soapMessage dataUsingEncoding: NSUTF8StringEncoding]];
// create the connection with the request
// and start loading the data, also set delegate to self
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection)
{
// Create the NSMutableData that will hold
webData=[[NSMutableData data] retain];
}
else
{
// inform the user that the download could not be made
NSLog(@”ERROR”);
}
}

That’s the essence to format the SOAP message and post the request.  In Objective C you’ll need to add the following for the methods of the NS objects we use:

– (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// clear any data that may be around.
[webData setLength:0];
}
– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// append the new data to the webData
// webData is declared in the header file
[webData appendData:data];
}
– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// Insert your code here to handle the problems created by connection failing with error
// Some typical things to handle:
// Release the connection, and the data object
[connection release];
[webData release];
// Display Alert UIAlertView
*errorNoConnection = [[UIAlertView alloc] initWithTitle:@”No Internet Connection” message:@”Unable to load site list” delegate:self cancelButtonTitle:@”OK” otherButtonTitles:nil];
[errorNoConnection show];
[errorNoConnection autorelease];
// Stop Indicator
[busySignal stopAnimating];
}
– (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Manipulate data here and release Data and Connection
NSLog(@”Succeeded! Received %d bytes of data\n”,[webData length]);
NSString *theXml = [[NSString alloc]initWithBytes:[webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
[theXml release];
// Parse received xml from web service
// We’ll insert some logic here to parse the XML in Part 2 of this post
// release the connection, and the data object
[connection release];
[webData release];
}

This is a pretty vanilla service to call but all basic nuts and bolts are all there to call a web service in Objective C.  In part 2 we’ll look at what we need to do to parse the xml and do something useful with the data.  Please feel free to comment or email me with any questions or suggestions you’d like to make in relation to this post.