Invoicing Gem - Sales & Payments In Your App

95
Sales & payments in your app Martin Kleppmann http://go-test.it http://yes-no-cancel.co.uk http://twitter.com/martinkl

description

Presentation given by Martin Kleppmann at Rails Underground in London on 24 July 2009. Gives an overview of how to develop a commercial B2B SaaS web app using Rails or other Ruby web frameworks, including best practices of structuring accouting data.

Transcript of Invoicing Gem - Sales & Payments In Your App

Page 1: Invoicing Gem - Sales & Payments In Your App

Sales & paymentsin your app

Martin Kleppmannhttp://go-test.it

http://yes-no-cancel.co.ukhttp://twitter.com/martinkl

Page 2: Invoicing Gem - Sales & Payments In Your App
Page 3: Invoicing Gem - Sales & Payments In Your App

Automated Cross-Browser Functional Testing

“Selenium in the cloud”

Page 4: Invoicing Gem - Sales & Payments In Your App

http://go-test.it

Page 5: Invoicing Gem - Sales & Payments In Your App

SaaS

Page 6: Invoicing Gem - Sales & Payments In Your App

Revenue model

Page 7: Invoicing Gem - Sales & Payments In Your App
Page 8: Invoicing Gem - Sales & Payments In Your App
Page 9: Invoicing Gem - Sales & Payments In Your App
Page 10: Invoicing Gem - Sales & Payments In Your App
Page 11: Invoicing Gem - Sales & Payments In Your App
Page 12: Invoicing Gem - Sales & Payments In Your App
Page 13: Invoicing Gem - Sales & Payments In Your App
Page 14: Invoicing Gem - Sales & Payments In Your App

You should be making one of

these

Page 15: Invoicing Gem - Sales & Payments In Your App

We needmoreofthese

Page 16: Invoicing Gem - Sales & Payments In Your App

We needmoreofthese

£

Page 17: Invoicing Gem - Sales & Payments In Your App

Your £1m business

e.g. £42/mon × 12 mon × 2,000 customers

Page 18: Invoicing Gem - Sales & Payments In Your App

Your £1m business

e.g. £42/mon × 12 mon × 2,000 customers

Automation!

Page 19: Invoicing Gem - Sales & Payments In Your App

B2B

Page 20: Invoicing Gem - Sales & Payments In Your App

Ruby Invoicing FrameworkSo… youʼve spent many nights developing your awesome application. Itʼs coming together nicely, and youʼve showed it to your friends, who got very excited about it too. In fact, people love your app so much that they are willing to pay you money to use it. Great news!Keeping it simple, you start taking payments trough PayPal or even accept cheques through the post. Later you maybe integrate with the API of a more flexible credit card handling provider. Money is coming in – even better news!The problems become apparent when you try to turn your app into a business. Suddenly everything becomes a lot more complicated. You need to start thinking about ugly things like tax and you need to pay an accountant to sort out the paperwork for you. You need to start bookkeeping, a prospect which gives you the shivers. Maybe some of your customers are awkward, accepting billing only in their own currency or requiring a special tax status. Itʼs all a bit of a mess, and as you grudgingly start ploughing through the Wikipedia page on “credits and debits”, you wish that you could just get the money and leave it at that.

The missing link between your app and the moneyEnter the Ruby Invoicing Framework RubyGem, or invoicing gem for short. Itʼs a collection of tools which provide the basic mechanisms for supporting financial transactions within your own application.

Page 21: Invoicing Gem - Sales & Payments In Your App

Ruby Invoicing FrameworkSo… youʼve spent many nights developing your awesome application. Itʼs coming together nicely, and youʼve showed it to your friends, who got very excited about it too. In fact, people love your app so much that they are willing to pay you money to use it. Great news!Keeping it simple, you start taking payments trough PayPal or even accept cheques through the post. Later you maybe integrate with the API of a more flexible credit card handling provider. Money is coming in – even better news!The problems become apparent when you try to turn your app into a business. Suddenly everything becomes a lot more complicated. You need to start thinking about ugly things like tax and you need to pay an accountant to sort out the paperwork for you. You need to start bookkeeping, a prospect which gives you the shivers. Maybe some of your customers are awkward, accepting billing only in their own currency or requiring a special tax status. Itʼs all a bit of a mess, and as you grudgingly start ploughing through the Wikipedia page on “credits and debits”, you wish that you could just get the money and leave it at that.

The missing link between your app and the moneyEnter the Ruby Invoicing Framework RubyGem, or invoicing gem for short. Itʼs a collection of tools which provide the basic mechanisms for supporting financial transactions within your own application.

http://ept.github.com/invoicing/

Page 22: Invoicing Gem - Sales & Payments In Your App

Richard Messenger, http://www.flickr.com/photos/richardmessenger/2626927255/

Page 23: Invoicing Gem - Sales & Payments In Your App
Page 24: Invoicing Gem - Sales & Payments In Your App

Production use

Page 25: Invoicing Gem - Sales & Payments In Your App

A solid foundation for building commercial

web apps

Page 26: Invoicing Gem - Sales & Payments In Your App

I’m not an accountant

Page 27: Invoicing Gem - Sales & Payments In Your App

Jargon

Page 28: Invoicing Gem - Sales & Payments In Your App

Jargon(as far as we can avoid it)

Page 29: Invoicing Gem - Sales & Payments In Your App

Installing

$ gem install invoicing invoicing_generator

$ script/generate invoicing_ledger billing \ --currency=GBP

$ rake db:migrate

Page 30: Invoicing Gem - Sales & Payments In Your App

Model classes

module Billing class Invoice < LedgerItem acts_as_invoice end class CreditNote < LedgerItem acts_as_credit_note end class Payment < LedgerItem acts_as_payment endend

Page 31: Invoicing Gem - Sales & Payments In Your App

Ledger items

Page 32: Invoicing Gem - Sales & Payments In Your App

•Invoice:“you owe us money”

Ledger items

Page 33: Invoicing Gem - Sales & Payments In Your App

•Invoice:“you owe us money”

•Credit Note:“oops, billed you too much”

Ledger items

Page 34: Invoicing Gem - Sales & Payments In Your App

•Invoice:“you owe us money”

•Credit Note:“oops, billed you too much”

•Payment:“thanks for the cash”

Ledger items

Page 35: Invoicing Gem - Sales & Payments In Your App

acts_as_ledger_item

module Billing class LedgerItem < ActiveRecord::Base acts_as_ledger_item has_many :line_items, :class_name => 'Billing::LineItem' belongs_to :sender, :class_name => 'Company' belongs_to :recipient, :class_name => 'Company' endend

Page 36: Invoicing Gem - Sales & Payments In Your App

Fine, butso what?

Page 37: Invoicing Gem - Sales & Payments In Your App

http://www.flickr.com/photos/26614375@N00/381941029/

Page 38: Invoicing Gem - Sales & Payments In Your App

Avoid writing boring code

Page 39: Invoicing Gem - Sales & Payments In Your App
Page 40: Invoicing Gem - Sales & Payments In Your App

Displaying an invoice

class BillingController < ApplicationController def document @document = Billing::LedgerItem.find(params[:id]) respond_to do |format| format.html { render :text => @document.render_html, :layout => true } format.xml { render :xml => @document.render_ubl } end endend

Page 41: Invoicing Gem - Sales & Payments In Your App

Displaying an invoice

class BillingController < ApplicationController def document @document = Billing::LedgerItem.find(params[:id]) respond_to do |format| format.html { render :text => @document.render_html, :layout => true } format.xml { render :xml => @document.render_ubl } end endend

Page 42: Invoicing Gem - Sales & Payments In Your App

Best practices

Page 43: Invoicing Gem - Sales & Payments In Your App

Your investors willwant to see

your accounts

Page 44: Invoicing Gem - Sales & Payments In Your App

•Exact dates and periods of invoices & payments

•Reconciling bank statements

•Details of VAT & other tax

What accountants need to know

Page 45: Invoicing Gem - Sales & Payments In Your App

http

://w

ww

.flic

kr.c

om/p

hoto

s/87

0494

3@N

07/3

4917

7972

2/

Page 46: Invoicing Gem - Sales & Payments In Your App

create_table "ledger_items" do |t| t.string "type" t.integer "sender_id" t.integer "recipient_id" t.string "currency", :default => "GBP", :null => false t.decimal "total_amount", :precision => 20, :scale => 4 t.decimal "tax_amount", :precision => 20, :scale => 4 t.string "status", :limit => 20 t.string "description" t.datetime "issue_date" t.datetime "period_start" t.datetime "period_end" t.datetime "created_at" t.datetime "updated_at"end

Dates & periods

Page 47: Invoicing Gem - Sales & Payments In Your App

create_table "ledger_items" do |t| t.string "type" t.integer "sender_id" t.integer "recipient_id" t.string "currency", :default => "GBP", :null => false t.decimal "total_amount", :precision => 20, :scale => 4 t.decimal "tax_amount", :precision => 20, :scale => 4 t.string "status", :limit => 20 t.string "description" t.datetime "issue_date" t.datetime "period_start" t.datetime "period_end" t.datetime "created_at" t.datetime "updated_at"end

Dates & periods

Page 48: Invoicing Gem - Sales & Payments In Your App

Invoice≠

Payment

(“bill”)

(“receipt”)

Page 49: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

Invoice ≠ Payment

Page 50: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

Invoice

+

Invoice ≠ Payment

Page 51: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

Invoice

+

Payment

+

Invoice ≠ Payment

Page 52: Invoicing Gem - Sales & Payments In Your App

Charges not yet invoiced

Description Amount

Pay As You Go charges so far this month £23.45

No. Date Description Amount

100 2009-06-01 Subscription for June £115.00

101 2009-06-24 Referral fee – thanks for inviting 3 friends –£10.00

102 2009-06-30 Credit card payment including PAYG credit –£200.00

Current account balance (GBP) –£75.00

Account statement

Page 53: Invoicing Gem - Sales & Payments In Your App

Charges not yet invoiced

Description Amount

Pay As You Go charges so far this month £23.45

No. Date Description Amount

100 2009-06-01 Subscription for June £115.00

101 2009-06-24 Referral fee – thanks for inviting 3 friends –£10.00

102 2009-06-30 Credit card payment including PAYG credit –£200.00

Current account balance (GBP) –£75.00

Account statement Invoice

Credit Note

Payment

Invoice(with status=open)

Page 54: Invoicing Gem - Sales & Payments In Your App

Account statement

class BillingController < ApplicationController def statement scope = Billing::LedgerItem. exclude_empty_invoices. sent_or_received_by(params[:id]). sorted(:issue_date)

@in_effect = scope.in_effect.all @open_or_pending = scope.open_or_pending.all @summary = Billing::LedgerItem.account_summary( params[:id]) endend

Page 55: Invoicing Gem - Sales & Payments In Your App

Thomas Hawk, http://www.flickr.com/photos/thomashawk/2317826708/

Page 56: Invoicing Gem - Sales & Payments In Your App

VAT

Page 57: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

VAT Account

Page 58: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

VAT Account

Invoice

+

Page 59: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

VAT Account

Payment

+

Invoice

+

Page 60: Invoicing Gem - Sales & Payments In Your App

Your Sales Account

Customer Account

Your Bank Account

VAT Account

Payment

+

Invoice

+

+

VATReturn

Page 61: Invoicing Gem - Sales & Payments In Your App

Urgh.(And we’ve not even started talking about EU

VAT regulations yet.)

Page 62: Invoicing Gem - Sales & Payments In Your App

create_table "ledger_items" do |t| t.string "type" t.integer "sender_id" t.integer "recipient_id" t.string "currency", :default => "GBP", :null => false t.decimal "total_amount", :precision => 20, :scale => 4 t.decimal "tax_amount", :precision => 20, :scale => 4 t.string "status", :limit => 20 t.string "description" t.datetime "issue_date" t.datetime "period_start" t.datetime "period_end" t.datetime "created_at" t.datetime "updated_at"end

VAT made easy

Page 63: Invoicing Gem - Sales & Payments In Your App

create_table "ledger_items" do |t| t.string "type" t.integer "sender_id" t.integer "recipient_id" t.string "currency", :default => "GBP", :null => false t.decimal "total_amount", :precision => 20, :scale => 4 t.decimal "tax_amount", :precision => 20, :scale => 4 t.string "status", :limit => 20 t.string "description" t.datetime "issue_date" t.datetime "period_start" t.datetime "period_end" t.datetime "created_at" t.datetime "updated_at"end

VAT made easy

Page 64: Invoicing Gem - Sales & Payments In Your App

create_table "ledger_items" do |t| t.string "type" t.integer "sender_id" t.integer "recipient_id" t.string "currency", :default => "GBP", :null => false t.decimal "total_amount", :precision => 20, :scale => 4 t.decimal "tax_amount", :precision => 20, :scale => 4 t.string "status", :limit => 20 t.string "description" t.datetime "issue_date" t.datetime "period_start" t.datetime "period_end" t.datetime "created_at" t.datetime "updated_at"end

VAT made easy

Page 65: Invoicing Gem - Sales & Payments In Your App

VAT made easy

# New in invoicing gem version 0.3class MyProduct < ActiveRecord::Base acts_as_taxable :price, :tax_logic => Invoicing::Countries::UK::VAT.newend

p = MyProduct.new :price => 10p.price_with_tax_info# => "£11.50 (inc. VAT)"

p.price_taxed = 23.00p.price.to_s# => "20.0"

Page 66: Invoicing Gem - Sales & Payments In Your App

Paolo Màrgari, http://www.flickr.com/photos/paolomargari/3050305454/

Page 67: Invoicing Gem - Sales & Payments In Your App

Overview of your customers

Page 68: Invoicing Gem - Sales & Payments In Your App

Sales and purchases ledger

Name Currency Sales Purchases Salereceipts

Purchasepayments Balance

A. N. Other GBP £400.00 £0.00 £400.00 £0.00 £0.00

Some Customer GBP £0.00 £395.00 £0.00 £250.00 –£145.00

Some Customer USD $2,782.31 $0.00 $2,160.61 $0.00 $621.70

Widgets Ltd GBP £229.63 £12.00 £300.00 £0.00 £82.37

Page 69: Invoicing Gem - Sales & Payments In Your App

Sales/purchase ledger

@summaries = Billing::LedgerItem.account_summaries(params[:id])

@summaries.each_pair do |id, by_currency| by_currency.each_pair do |currency, data| puts "Sales: #{data.sales_formatted}" puts "Purchases: #{data.purchases_formatted}" # ... endend

Page 70: Invoicing Gem - Sales & Payments In Your App

What else?

Page 71: Invoicing Gem - Sales & Payments In Your App

Mar

tin K

lepp

man

n, h

ttp:

//ww

w.fl

ickr

.com

/pho

tos/

mar

tinkl

eppm

ann/

3131

1987

70/

Page 72: Invoicing Gem - Sales & Payments In Your App

Mar

tin K

lepp

man

n, h

ttp:

//ww

w.fl

ickr

.com

/pho

tos/

mar

tinkl

eppm

ann/

3131

1987

70/

¥1,300

Page 73: Invoicing Gem - Sales & Payments In Your App

Currency formatting

Page 74: Invoicing Gem - Sales & Payments In Your App

Currency formatting

inv = Billing::MyInvoice.new :currency => 'JPY'nov = Billing::LineItem.new( :description => 'November charge', :net_amount => 10, :tax_point => '2008-11-30')inv.line_items << nov; inv.save!

nov.amount_formatted# => "¥10"inv.currency = 'GBP'nov.amount_formatted

Page 75: Invoicing Gem - Sales & Payments In Your App

Nothing is constant

Page 76: Invoicing Gem - Sales & Payments In Your App

VAT change 1/12/09

dec = Billing::LineItem.new( :description => 'December charge', :net_amount => 10, :tax_point => '2008-12-01')inv.line_items << dec

nov.amount_taxed_formatted# => "£11.75"dec.amount_taxed_formatted# => "£11.50"

Page 77: Invoicing Gem - Sales & Payments In Your App

John

ny V

ulka

n, h

ttp:

//ww

w.fl

ickr

.com

/pho

tos/

2661

4375

@N

00/3

8194

1029

/

Page 78: Invoicing Gem - Sales & Payments In Your App

Integrating with payment gateways

⇒ http://activemerchant.org

Page 79: Invoicing Gem - Sales & Payments In Your App

Open standards

Page 80: Invoicing Gem - Sales & Payments In Your App

Displaying an invoice

class BillingController < ApplicationController def document @document = Billing::LedgerItem.find(params[:id]) respond_to do |format| format.html {

render :text => @document.render_html, :layout => true } format.xml { render :xml => @document.render_ubl } end endend

Page 81: Invoicing Gem - Sales & Payments In Your App

Displaying an invoice

class BillingController < ApplicationController def document @document = Billing::LedgerItem.find(params[:id]) respond_to do |format| format.html {

render :text => @document.render_html, :layout => true } format.xml { render :xml => @document.render_ubl } end endend

Page 82: Invoicing Gem - Sales & Payments In Your App

Displaying an invoice

class BillingController < ApplicationController def document @document = Billing::LedgerItem.find(params[:id]) respond_to do |format| format.html {

render :text => @document.render_html, :layout => true } format.xml { render :xml => @document.render_ubl } end endend

UBL? WTF?

Page 83: Invoicing Gem - Sales & Payments In Your App

UBL = “Universal Business Language”

OASIS Open Standard

Page 84: Invoicing Gem - Sales & Payments In Your App

UBL: If you’re working with invoices and purchase orders

and that kind of stuff (and who isn’t?) [...] Look no further.

@timbray: “Don’t Invent XML Languages”http://tr.im/NoNewXML

Page 85: Invoicing Gem - Sales & Payments In Your App

UBL Example (1/3)

<ubl:Invoice xmlns:ubl="..." xmlns:cbc="..." xmlns:cac="..."> <cbc:ID>1</cbc:ID> <cbc:IssueDate>2008-06-30</cbc:IssueDate> <cac:InvoicePeriod> <cbc:StartDate>2008-06-01</cbc:StartDate> <cbc:EndDate>2008-07-01</cbc:EndDate> </cac:InvoicePeriod> <cac:AccountingSupplierParty> ... </cac:AccountingSupplierParty> <cac:AccountingCustomerParty> ... </cac:AccountingCustomerParty>...

Page 86: Invoicing Gem - Sales & Payments In Your App

UBL Example (2/3)

<cac:TaxTotal> <cbc:TaxAmount currencyID="GBP"> 15.00 </cbc:TaxAmount> </cac:TaxTotal> <cac:LegalMonetaryTotal> <cbc:TaxExclusiveAmount currencyID="GBP"> 100.00 </cbc:TaxExclusiveAmount> <cbc:PayableAmount currencyID="GBP"> 115.00 </cbc:PayableAmount> </cac:LegalMonetaryTotal>

Page 87: Invoicing Gem - Sales & Payments In Your App

UBL Example (3/3)

<cac:InvoiceLine> <cbc:ID>42</cbc:ID> <cbc:LineExtensionAmount currencyID="GBP"> 100.00 </cbc:LineExtensionAmount> <cac:Item> <cbc:Description> Subscription for my fantastic app </cbc:Description> </cac:Item> </cac:InvoiceLine></ubl:Invoice>

Page 88: Invoicing Gem - Sales & Payments In Your App

@timbray: “Don’t Invent XML Languages”http://tr.im/NoNewXML

Designing XML Languages is hard. It’s boring, political, time-

consuming, unglamorous, irritating work.

Page 89: Invoicing Gem - Sales & Payments In Your App

Interoperability

Page 90: Invoicing Gem - Sales & Payments In Your App

OAccountsSage

MYOB

KashFlow

Xero

Invoicing gem

Payment provider

Shopping cart

Custom reporting

Page 91: Invoicing Gem - Sales & Payments In Your App

OAccountsSage

MYOB

KashFlow

Xero

Invoicing gem

Payment provider

Shopping cart

Custom reporting

OAccounts

Page 92: Invoicing Gem - Sales & Payments In Your App

OAccounts=

UBL + XBRL-GL + REST + Conventions +

Documentation +Collaboration +

Open source implementation

Page 93: Invoicing Gem - Sales & Payments In Your App

OAccounts=

UBL + XBRL-GL + REST + Conventions +

Documentation +Collaboration +

Open source implementation

http://oaccounts.org/

Page 94: Invoicing Gem - Sales & Payments In Your App

Image credits

Screenshots of:http://basecamphq.com/signup, http://freshbooks.com/pricing.php, http://fogcreek.com/FogBugz/,http://github.com/plans, http://lessaccounting.com/pricing, http://freeagentcentral.com/pricing, http://huddle.net/huddle-price-plans/, http://twitter.com/bensummers/status/1199722134,http://oneis.co.uk/, http://bidforwine.co.uk

Building site: Richard Messenger, http://www.flickr.com/photos/richardmessenger/2626927255/

Tim Bray: http://en.wikipedia.org/wiki/File:Tim_Bray.jpg

Pile of money: Johnny Vulkan, http://www.flickr.com/photos/26614375@N00/381941029/

Astronomical clock: magro_kr, http://www.flickr.com/photos/8704943@N07/3491779722/

Tax Service: Thomas Hawk, http://www.flickr.com/photos/thomashawk/2317826708/

Man in a shop: Paolo Màrgari, http://www.flickr.com/photos/paolomargari/3050305454/

Hands full of money: Marshall Astor, http://www.flickr.com/photos/lifeontheedge/2672465894/

Page 95: Invoicing Gem - Sales & Payments In Your App

Martin Kleppmannhttp://go-test.it

http://yes-no-cancel.co.ukhttp://twitter.com/martinkl

Thank you!