How We Build Our Own Quotes With ExpressionEngine
For a small web shop, creating estimates and quotes can be a joy killer. I just want to make stuff, man - not write out endless spec documents! It's true. Being old school print designers let me tell you how this process went for years:
- Open up our quote InDesign document
- Save it as a new file
- Pour over every legal aspect to make sure it was right
- Do the whole spec part of the job in the middle
- Make sure all the styles were right so it would look awesome
- Do all the math (arghhh)
- Save as a PDF
- Email it
And. We. Hated. It.
When we rebuilt and re-designed the site last year we knew some things had to change. First of all, we didn't want to go through that huge document and re-do all the styles. Bleh. Second of all, it had become a huge bottleneck and we wanted to fix that.
Separating Scope and Legal
Our first hint came from one of Less Everything's Less Money workshops a couple of years ago. They shared a legal contract that they use for all their clients and then add a scope of work separately. “Hey that makes sense.” Why have all that legal stuff that barely changes anyway be on the estimate? It's ripe for mistakes and a barrier to entry for the client.
So we created a Google Doc and link all of our clients to it as part of our estimate. Again, it's just the legal side of stuff, not anything specific to their project. That's where we got creative.
Building our own Quoting Engine
Another piece of the puzzle was that we moved to hourly pricing last year as well. So this was going to change how we created estimates anyway. It was time to do something different. Looking at our bottleneck, we spent all our time on styling the text and doing the math. The actual “we're doing this and it will cost this much” part was easy.
After doing all the work rebranding our website I started to think, “What if our quotes were just built in to the site - that way we inherit all the styles automatically and if we do rebrand again it comes along for the ride?” And then I thought, “Our site is built in ExpressionEngine which is crazy powerful - surely we could create a channel that lets us input the content, easily style it with a WYSIWYG and do all the math for us!” And then I got excited. 'Cause that was a good idea.
Thanks to a few Add-On's it wasn't that hard, either. Here's a picture of how we enter the data:
Basically we just used Wygwam and Matrix to allow us to repeat major sections. So Design would get it's own row, HTML/CSS would be on another row, etc… This lets us build custom quotes really fast while keeping styles in tact. We also threw in an expenses field since it was a dollar amount and not an hourly amount.
On the template side we used MX Calculator and Price Format as well as the built in sum functions in Matrix to add everything up. That was probably the trickiest part.
And just like that, it got stupid easy to build a quote for someone. We have links hardcoded to the legal document and a billing policy document so we just password protect it, send them a link with login information and they can literally print, sign and email back to us from right there. Since our site is responsive, even printing the page works, too.
We've been using this for at least a year and it's taken such a load off when creating estimates. So I thought you might find it useful, too. Here's how we made it:
What You'll Need
- Your Site
- Print Styles
- ExpressionEngine License
- Matrix
- Wygwam
- MX Calculator
- Price Format
Then create a channel called Quote - shortname {quote}
and create these fields:
- Client -
{quote_client}
- text field - Hourly Rate -
{quote_hourly_rate}
- text field - Discovery/Deposit -
{quote_discovery}
- text field - Quote Table -
{quote_table
} - Matrix with two columns - Wygwam field called{desc}
and a text field called{hour_low}
- Expenses Table -
{quote_expenses_table}
- Also a Matrix with two columns - Wygwam field called{desc}
and a text field called{amount}
The hourly rate field lets you adjust per quote if you decide to raise your rates or give a non-profit a discount. The deposit fields lets you add an additional fee to the quote if you need to. We also use the expiration date filed built into EE so they know how long the price is good for. And we've already talked about how the quote table and expenses table work.
Finally, you'll need two templates. One for the main file and one to do your number formatting. I've stripped down the main one as much as I can, but it's still pretty long:
<!DOCTYPE html> <html> <head> {exp:channel:entries channel="quote" limit="1" disable="pagination|categories|member_data|trackbacks" url_title="{segment_2}"} <meta name="description" content="{summary}" /> <title>{title} | Estimate | {site_name}</title> <!-- Stop search engines from indexing your estimates :)--> <meta name="robots" content="noindex,nofollow"> {/exp:channel:entries} </head> <body class="estimate"> <div id="content"> {if logged_in} {exp:channel:entries channel="quote" limit="1" disable="member_data|trackbacks" url_title="{segment_2}"} <h1>Exhibit A: Estimate for {quote_client}</h1> <p class="date">{entry_date format='%F %d, %Y'} - price good until {expiration_date format='%F %d, %Y'}</p> <table cellspacing="0" cellpadding="0"> <thead> <tr> <th scope="col" class="desc">Description</th> <th scope="col" class="hour_low">Hours</th> </tr> </thead> <tbody> {quote_table} <tr> <td class="desc">{desc}</td> <td class="hour_low">{hour_low} <span>hrs</span></td> </tr> {/quote_table} {quote_expenses_table} <tr> <td class="desc">{desc}</td> <td class="hour_low">${amount}</td> </tr> {/quote_expenses_table} <tr> <td class="desc"><h3>Total</h3></td> <td class="hour_low total">{quote_table:sum col="hour_low"} <span>hrs</span> <br /> <span class="multiply">x </span> ${quote_hourly_rate}<span>/hr</span><br /><hr /> {exp:mx_calc expression="{quote_table:sum col="hour_low"}*{quote_hourly_rate}"} ${embed="quotes/calc" result="{calc_result}"} {/exp:mx_calc}<br /> <span class="multiply">+ expenses </span> ${embed="quotes/calc" result="{quote_expenses_table}{amount}{/quote_expenses_table}"} <br /> {if quote_discovery != "0"} <span class="multiply">+ discovery/deposit </span> ${embed="quotes/calc" result="{quote_discovery}"} <br />{/if} <hr /> <h2>{exp:mx_calc expression="({quote_table:sum col="hour_low"}*{quote_hourly_rate})+{quote_discovery}+{quote_expenses_table}{amount}{/quote_expenses_table}"} ${embed="quotes/calc" result="{calc_result}"} {/exp:mx_calc}</h2> </td> </tr> </tbody> </table> <p class="disclaimer"><em>Hours are billed in 30 minute increments. See contract and billing document for additional information.</em></p> <h2>Signatures</h2> <div class="signature"><hr />{quote_client} Representative</div> <div class="signature last"><hr />{site_name} Representative</div> <div class="signature"><hr />Date</div> <div class="signature last"><hr />Date</div> {/exp:channel:entries} {/if} {if logged_out} <h1>Client Quote Login</h1> <p>Hey there! If you're a potential client just login with the info we gave you to see your quote.</p> {/if} </div><!--End Content--> <div id="sidebar"> {if logged_out} {exp:member:login_form return="/quotes/{segment_2}"} <div class="loginbox clearfix"> <label>Username</label> <input class="text required" type="text" name="username" value="" maxlength="32" size="25"> <label>Password</label> <input class="text required" type="password" name="password" value="" maxlength="32" size="25"> {if auto_login} <p><input type="checkbox" name="auto_login" value="1"> Auto-login on future visits</p> {/if} <span class="button"><input name="submit" type="submit" value="Submit" /></span> {/exp:member:login_form} </div> {/if} {if logged_in} <div class="contact-section clearfix"> <h2>Sign These</h2> <ul> <li class="print"><a href="#" onclick="javascript:window.print();">Print/Sign This Page</a></li> <li class="download"><a href="#">Quote Agreement</a></li> </ul> <h2>Read This</h2> <ul> <li class="download"><a href="#">Billing Policy</a></li> </ul> </div> <p class="logout"><em><a href="{path='logout'}">Log Out</a></em></p> {/if} </div> </body> </html>
And the second template - {calc}
is just this:
{exp:price_format price="{embed:result}" decimals="0"}
How it works now
So after a little bit of work we have a really great system in place for creating estimates. Our process now is just this:
- Log into ExpressionEngine
- Publish a new quote entry (or use MX Cloner to re-use as much as possible from an old one)
- Enter content and hours
- Have it automagically styled and added up
- Email it
You can obviously adjust as needed, but I thought having the math already put together would be helpful. If copying and pasting isn't your thing, I've made text files for you to download, too. So, if your quoting process is driving you crazy and your site is already built with ExpressionEngine give this a shot! Shoudn't take too long to setup and you'll save tons of time creating estimates in the long run.
Enjoy!
Comments
1
Mike Lohrman - Aug 01, 2013
Jonathan Longnecker - Aug 01, 2013
3
Todd - Aug 01, 2013
4
Lincoln Gbenga Olagbaju - Aug 02, 2013
5
Jules - Aug 02, 2013
Jonathan Longnecker - Aug 02, 2013
7
John Derrick - Aug 03, 2013
8
Andrew Armitage - Aug 03, 2013
Jonathan Longnecker - Aug 05, 2013
10
Seth - Aug 13, 2013
Jonathan Longnecker - Aug 13, 2013
12
Ashley - Aug 15, 2013
Jonathan Longnecker - Aug 15, 2013
14
edward - Nov 17, 2013
Jonathan Longnecker - Nov 18, 2013
16
edward - Nov 18, 2013
Jonathan Longnecker - Nov 18, 2013
18
Darin - Nov 17, 2014
Jonathan Longnecker - Nov 18, 2014
20
Darin - Nov 18, 2014
Jonathan Longnecker - Nov 19, 2014
Jonathan Longnecker - Nov 19, 2014
23
jati jepara - Jun 30, 2015
24
raju - Jul 24, 2015