Here are the main design goals:
[UPDATE June 2008: The bare functionality needed to operate the site would be the ability to schedule equipment and accounting reports.]
In comparison to the current prototype...
...easier to create reservations. Single page, faster loading, faster response. Creation and editing from one page without having to load new page. Use AJAX so user never has to leave the page until they're finished creating or revising the reservation. This alone should address the faster response goal.
...better conflict detection and resolution. Detect conflicts by time and date, allow clients to specify desired pickup and return times, keep like items generic until pulled for pickup or specific item reserved for client. Current prototype just tracks items by date, assuming "latest return time" and "earliest pickup times" are fixed at 11am and 2pm respectively. But enough clients want to pickup in the morning and return late in the day, sometimes on the same day. Also, a c-stand is a c-stand is a c-stand, so don't reserve a specific c-stand for someone when they can use any c-stand in the shop. Keep things like c-stand generic will eliminate the "false conflict" when two specific c-stands are booked for two different, non-overlapping reservations, preventing a third reservation from booking a c-stand because it overlaps with one or both of those reservations and we only have two c-stands available for that time period. (The first two non-overlapping reservations could have shared the same c-stand, freeing up the second c-stand for the third reservation.)
...faster searches. Live search form for clients and equipment. Have one form that lets user search for any client by typing in a few letters and performing an partial search. Using AJAX will show the search results as the letters are typed. Can use client-side javascript to search within the initial search results if the original letters are added and not subtracted from. Require at least three letters or a time delay to cut down on the returned results. Allow searching for clients and equipment or just clients/just equipment.
...better accounting reports. Change the database to track different data so reports are easier to generate and more detailed. Current prototype does not track accounting information, only schedules equipment and generates contracts. From this information, I've been able to cobble together reports of totals by client and reservations. But this is not enough, it requires too much manual data manipulation for accounting. Especially when we are handling third-party equipment where we have to track commissions due these third-party owners. New design needs a register per account so that debits and credits can be recorded and reported.
...better client experience. Easier database maintenance and online quotes and reservations. Current prototype has waaay too many clicks and page loads to update public website information. Use AJAX to implement in-place editing of any equipment data, posts, and (hopefully) all other page content. Allow anyone who signs up for a user account to assemble packages and get a real-time quote for the number of days they need that package, then let them submit that package for a specific date range for us to confirm or revise if conflicts exist for that time period (in other words, users are not able to detect conflicts). Allow trusted users to see conflicts and let them actually reserve equipment for a specific date range (subject to final approval). Give a discount for booking online since that frees us up to do other things than book equipment over the phone or over email.
...better access control. Provide role-based access and auditing. Current prototype has only one admin account and only tracks revision dates. Need ability to assign roles and level of access to employees so that accounts are protected, contracts can be locked, and only trusted employees are allowed to make changes to published information. Track who makes changes to contracts and (hopefully) provide ability to rollback changes or at least see what those changes were so that errors can be corrected.
...better public interface. Easier to search for items, RSS feed, community integration. Allow users to find information faster using simplified navigation. Provide for better accessibility for users with disabilities (get rid of tables, easier navigation). Provide RSS feed for posts, tips, news, links, anything of interest. Allow trusted users to become authors, where they can post news, articles and links. Allow trusted users to comment on equipment, articles, news and links.
...better user communication. Automated email reminders, account reports, rewards. Send emails to confirm reservations prior to cancellation penalty. Provide ability to control how automated particular emails are (admin confirmation required before sending). For third-party equipment owners, send email to: let them know when reservations for their equipment are booked, canceled, revised; remind them to bring in their equipment in time for rental pickups; let them know when their equipment comes back in for them to pickup; access reports to see when their equipment is booked, how much they are owed, get past bookings. For users, let them access their account to see if they owe money, have credit, get past receipts, check upcoming reservations. For authors, let them revise their articles, news, links and respond to comments. Reward good clients with credit or discounts by keeping track of their ratings (not published), frequency of rentals, total sales and reservation totals.
...better maintainability. Code needs to be extended and maintained. Use behavior driven development as much as possible to provide tests to catch (hopefully) most bugs. Stick to MVC, DRY and convention-over-configuration principles. Refactor code that gets too long, too many indents, too many methods in one file. Use natural language for methods and attributes. Add comments when all else fails to describe the function (comments tend to get outdated).
Wednesday, January 30, 2008
Documenting a moderately complex web app
My goal is to document the implementation and refactoring of a web-based app built on Rails with Ruby (currently running on PHP with no framework). This will be more to help me remember design choices and learn the plugins that are used in the design. But if it's helpful to others, that's cool.
Here's a short description of the app: a rental equipment scheduling and accounting app with extensions for a built-in social network to help film crew and producers to connect. I operate a video equipment rental company in Austin, Texas called Mopac Media (I may change the name of the company to something more descriptive of our business model) but in a past life I used to be a EE and a software developer.
So Mopac Media needs to keep track of equipment rentals, clients and accounts. Sounds simple but we need to avoid conflicts when scheduling our equipment. We have a limited number of items and we can get overbooked if we're not careful, like back in the bad old days when all we had was a Yahoo! group calendar. Yeesh. (It worked back then because we didn't have as much business.)
Another complicating factor is that most of our equipment are collections of our equipment. Like a lighting package is a collection of lights which are themselves a collection of lighting fixture, light stand, barndoors, etc. So it's a tree with many-to-many self-referential polymorphic associations (group, collection, inventory item) where the leaves of the tree (inventory items) connect to physical inventory.
So checking for conflicts becomes a big deal because we need to check for conflicts based on dates AND inventory levels.
But I think I've come up with a monkey-clever design of three tables, where the first table is our master table that implements a directed acyclic graph (DAG) and the other two tables implement a nested set of the DAG (for easily obtaining needed inventory count) and a straight-forward table that maps inventory items to dates those items are reserved. These last two tables can be completely deleted and re-created from other database records, either on demand or upon an event.
Anyway, that's the explanation in one paragraph. It's a bit more complicated than that but that's the essence.
The beauty is that with Rails and a collection of plugins, I should be able to produce manageable code to do this, with tests! I've been working on the design for the past year (2007) and now that Rails 2.0 is finally here (update: and now Heroku), I'll be able to stand upon the shoulders of giants and command an impressive view of my domain. Bwu-ha-hah!
(Big thanks to everyone in the open source community! I hope to give back by making this app freely and publicly available to other business owners. Only the reporting feature will be required.)
Here's the history of the app: I started the business and cobbled together a static website so people could see what equipment I had available for rent, the rates for everything and how to contact me. Once the business had grown and maintaining the site became a headache, a good friend of mine offered to build me a PHP website with admin interface to a MySQL DB.
He got it running and it was terrific. I could update equipment, rates and everything on the website without having to touch HTML, almost. But I was over-booking the equipment like mad at this point and so over a one-month period I figured out how PHP, MySQL and his code worked and built a custom reservation system. Awesome! No more over-bookings, almost.
That was four years ago and I've learned a lot more about the problem domain, like what reports we need to run the business side, and usability. I'd solved the problem of over-booking but now it's now a maintenance headache keeping the equipment information updated and booking equipment rentals. It takes way too many clicks to get these things done.
And of course my PHP code is nasty with no Controller/View separation and non-DRY models.
So I began to re-code the site in PHP with view templates and a DRYer model framework. Then I re-discovered Ruby on Rails. I'd discovered it at an early state when it offered very basic functionality with minimal model associations, not suitable to the task. But now with Rails 2.0, it's ready to handle the new app.
(I don't think it's the fault of PHP specifically, I'll take a lot of the blame, but Ruby looks so sexy in the way it facilitates domain specific language, promotes ease of reading, reasonable object orientation with class features better than PHP and with less potential for abuse than C++, and a super groovy cool developer community.)
So that's the not-so-skinny. I'm considering my PHP app as a fantastic prototype, something that's kept us going over the years but nonetheless a throw-away prototype. And I love throwing away crap and building something less crappy. And I love learning cool new tools which of course will someday become crap as well. But in the meantime, they are really cool.
The current site: http://www.mopacmedia.com -- sorry, no public or guest access to the reservation system. You'll just have to take my word that it's cool, our clients like it, but it's ugly now and we need something better.
Onward!
Here's a short description of the app: a rental equipment scheduling and accounting app with extensions for a built-in social network to help film crew and producers to connect. I operate a video equipment rental company in Austin, Texas called Mopac Media (I may change the name of the company to something more descriptive of our business model) but in a past life I used to be a EE and a software developer.
So Mopac Media needs to keep track of equipment rentals, clients and accounts. Sounds simple but we need to avoid conflicts when scheduling our equipment. We have a limited number of items and we can get overbooked if we're not careful, like back in the bad old days when all we had was a Yahoo! group calendar. Yeesh. (It worked back then because we didn't have as much business.)
Another complicating factor is that most of our equipment are collections of our equipment. Like a lighting package is a collection of lights which are themselves a collection of lighting fixture, light stand, barndoors, etc. So it's a tree with many-to-many self-referential polymorphic associations (group, collection, inventory item) where the leaves of the tree (inventory items) connect to physical inventory.
So checking for conflicts becomes a big deal because we need to check for conflicts based on dates AND inventory levels.
But I think I've come up with a monkey-clever design of three tables, where the first table is our master table that implements a directed acyclic graph (DAG) and the other two tables implement a nested set of the DAG (for easily obtaining needed inventory count) and a straight-forward table that maps inventory items to dates those items are reserved. These last two tables can be completely deleted and re-created from other database records, either on demand or upon an event.
Anyway, that's the explanation in one paragraph. It's a bit more complicated than that but that's the essence.
The beauty is that with Rails and a collection of plugins, I should be able to produce manageable code to do this, with tests! I've been working on the design for the past year (2007) and now that Rails 2.0 is finally here (update: and now Heroku), I'll be able to stand upon the shoulders of giants and command an impressive view of my domain. Bwu-ha-hah!
(Big thanks to everyone in the open source community! I hope to give back by making this app freely and publicly available to other business owners. Only the reporting feature will be required.)
Here's the history of the app: I started the business and cobbled together a static website so people could see what equipment I had available for rent, the rates for everything and how to contact me. Once the business had grown and maintaining the site became a headache, a good friend of mine offered to build me a PHP website with admin interface to a MySQL DB.
He got it running and it was terrific. I could update equipment, rates and everything on the website without having to touch HTML, almost. But I was over-booking the equipment like mad at this point and so over a one-month period I figured out how PHP, MySQL and his code worked and built a custom reservation system. Awesome! No more over-bookings, almost.
That was four years ago and I've learned a lot more about the problem domain, like what reports we need to run the business side, and usability. I'd solved the problem of over-booking but now it's now a maintenance headache keeping the equipment information updated and booking equipment rentals. It takes way too many clicks to get these things done.
(I don't think it's the fault of PHP specifically, I'll take a lot of the blame, but Ruby looks so sexy in the way it facilitates domain specific language, promotes ease of reading, reasonable object orientation with class features better than PHP and with less potential for abuse than C++, and a super groovy cool developer community.)
So that's the not-so-skinny. I'm considering my PHP app as a fantastic prototype, something that's kept us going over the years but nonetheless a throw-away prototype. And I love throwing away crap and building something less crappy. And I love learning cool new tools which of course will someday become crap as well. But in the meantime, they are really cool.
The current site: http://www.mopacmedia.com -- sorry, no public or guest access to the reservation system. You'll just have to take my word that it's cool, our clients like it, but it's ugly now and we need something better.
Onward!
Welcome to SlipShodFishBarrel
The obligatory welcome message! Why SlipShodFishBarrel? It was available. Enjoy! :D...
Subscribe to:
Posts (Atom)