Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for prices including taxes for #1

Merged
merged 1 commit into from Sep 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/helpers/application_helper.rb
Expand Up @@ -10,12 +10,12 @@ def default_body
Extras: {% for extra in plan.extras %}
{{extra.name}}: {{extra.price | money }} {{plan.currency}}
{% endfor %}{% endif %}
Price: {{plan.price_per_cycle | money}} {{plan.currency}}.
Price: {{plan.price | money}} {{plan.currency}}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wenn du den namen des attributes änderst, gehen alle bestehenden reminder kaputt. gibt's da noch nen alias drauf?


{% if paid_for_members %}
In addition you are paying for these members:
{% for m in paid_for_members %}
{{m.address.name}}: {{ m.plan.name }}, {{m.plan.price_per_cycle | money}} {{m.plan.currency}}
{{m.address.name}}: {{ m.plan.name }}, {{m.plan.price | money}} {{m.plan.currency}}
{% endfor %}
{% endif %}

Expand Down
2 changes: 1 addition & 1 deletion app/helpers/liquid_helper.rb
@@ -1,7 +1,7 @@
module LiquidHelper
module MoneyFilter
def money(input)
sprintf('%.2f', input.to_f)
sprintf('%.2f', input.to_f.round(2))
end
end

Expand Down
4 changes: 3 additions & 1 deletion app/models/extra.rb
@@ -1,13 +1,15 @@
class Extra
include Virtus.model
include Pricable

attribute :name, String
attribute :price_in_cents, Fixnum
attribute :price, BigDecimal
attribute :tax_rate, BigDecimal
attribute :charge_taxes, Boolean

def initialize(*args)
super
self.price = BigDecimal.new(price_in_cents.to_s) / 100.0
end

def to_liquid
Expand Down
7 changes: 5 additions & 2 deletions app/models/membership.rb
Expand Up @@ -7,9 +7,12 @@ class Membership
attribute :upcoming_plan, Plan
attribute :address, Address
attribute :next_invoice_at, Date
attribute :charge_taxes, Boolean

def initialize(attribute)
super attribute
def initialize(attributes)
attributes[:plan][:charge_taxes] = attributes[:charge_taxes]
attributes[:upcoming_plan][:charge_taxes] = attributes[:charge_taxes] if attributes[:upcoming_plan]
super attributes
end

def current_plan
Expand Down
22 changes: 17 additions & 5 deletions app/models/plan.rb
@@ -1,20 +1,32 @@
class Plan
include Virtus.model
include Pricable

attribute :name, String
attribute :price_per_cycle_in_cents, Fixnum
attribute :price_per_cycle, BigDecimal
attribute :price, BigDecimal
attribute :currency, String
attribute :canceled_to, Date
attribute :extras, [Extra], default: []
attribute :tax_rate, BigDecimal
attribute :charge_taxes, Boolean

# Backwards compability with api still using price_per_cycle_in_cents
alias_method :price_in_cents, :price_per_cycle_in_cents
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, dann hat sich die frage oben erledigt


# Backwards compability with old templates that use price_per_cycle instead of price
attribute :price_per_cycle, BigDecimal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wobei, wozu brauchst du nen attribute und danach noch ne methode. muesste nicht nur die methode reichen?

def price_per_cycle
price
end

def initialize(*args)
super
self.price_per_cycle = BigDecimal.new(price_per_cycle_in_cents.to_s) / 100.0
def initialize(attributes)
attributes[:extras].each{|extra| extra[:charge_taxes] = attributes[:charge_taxes]} if attributes[:extras]
super attributes
end

def free?
price_per_cycle == 0
price == 0
end

def attributes
Expand Down
7 changes: 7 additions & 0 deletions app/models/pricable.rb
@@ -0,0 +1,7 @@
module Pricable
def initialize(*args)
super
self.price = BigDecimal.new(price_in_cents.to_s) / 100.0
self.price = price * (tax_rate / 100 + 1) if charge_taxes
end
end
2 changes: 1 addition & 1 deletion app/views/reminders/_form.html.erb
Expand Up @@ -3,6 +3,6 @@
<%= f.input :subject, label: 'Email subject' %>
<%= f.input :bcc, label: 'Bcc', hint: "Send a copy of each email to this address" %>
<%= f.input :body, label: 'Email body',
hint: "You can use <a href=\"http://docs.shopify.com/themes/liquid-documentation/basics\">Liquid</a> markup here:<br/><em>{{plan.name}}</em> will be replaced with the plan's name.<br/> <i>{{plan.price_per_cycle | money}}</i> will print out the plan's price.<br/> You can also use: <i>plan.currency</i>, <i>plan.extras</i> (where each extras has a <i>name</i> and a <i>price</i> field) <i>days</i> (no. of days until invoice is sent) and any of <i>member.address.name/member.address.first_name/company/address/city/state/post_code/country</i>.".html_safe,
hint: "You can use <a href=\"http://docs.shopify.com/themes/liquid-documentation/basics\">Liquid</a> markup here:<br/><em>{{plan.name}}</em> will be replaced with the plan's name.<br/> <i>{{plan.price | money}}</i> will print out the plan's price.<br/> You can also use: <i>plan.currency</i>, <i>plan.extras</i> (where each extras has a <i>name</i> and a <i>price</i> field) <i>days</i> (no. of days until invoice is sent) and any of <i>member.address.name/member.address.first_name/company/address/city/state/post_code/country</i>.".html_safe,
input_html: {rows: 9, value: (default_body if f.object.body.blank?), class: 'input-xxlarge input-block-level'} %>
<%= f.input :days_before, hint: 'Send the email x days before the invoice is due.', input_html: {min: 1} %>
8 changes: 4 additions & 4 deletions spec/integration/manage_invoice_reminders_spec.rb
Expand Up @@ -20,7 +20,7 @@

it 'shows an error when posting invalid markup' do
fill_in 'Email subject', with: 'invoice coming'
fill_in 'Email body', with: 'price: {{ plan.price_per_cycle }'
fill_in 'Email body', with: 'price: {{ plan.price }'
fill_in 'Days before', with: '4'
click_button 'Set Reminder'

Expand All @@ -29,7 +29,7 @@

it 'shows an error when previewing invalid markup' do
fill_in 'Email subject', with: 'invoice coming'
fill_in 'Email body', with: 'price: {{ plan.price_per_cycle }'
fill_in 'Email body', with: 'price: {{ plan.price }'
fill_in 'Days before', with: '4'
click_button 'Preview'

Expand All @@ -38,7 +38,7 @@

it 'lets me preview the email body' do
fill_in 'Email subject', with: 'invoice coming'
fill_in 'Email body', with: 'plan: {{plan.name}}, price: {{plan.price_per_cycle | money}} {{plan.currency}}'
fill_in 'Email body', with: 'plan: {{plan.name}}, price: {{plan.price | money}} {{plan.currency}}'
fill_in 'Days before', with: '4'
click_button 'Preview'

Expand Down Expand Up @@ -81,7 +81,7 @@
visit space_reminders_path('mutinerie')
click_link 'Edit'

fill_in 'Email body', with: 'price: {{ plan.price_per_cycle }'
fill_in 'Email body', with: 'price: {{ plan.price }'
click_button 'Preview'

expect(page).to have_content('properly terminated')
Expand Down
14 changes: 7 additions & 7 deletions spec/integration/send_invoice_reminder_spec.rb
Expand Up @@ -7,7 +7,7 @@
body: <<-TXT,
Hi {{ member.address.name }}. You will be receiving an invoice for your
plan {{ plan.name }} costing
{{plan.price_per_cycle | money}} {{plan.currency}} in {{days}} days.
{{plan.price | money}} {{plan.currency}} in {{days}} days.
Extras: {% for extra in plan.extras %} {{extra.name}}: {{extra.price | money}} {{plan.currency}} {% endfor %}
TXT
days_before: 5 do |r|
Expand All @@ -19,9 +19,9 @@

it 'sends an email to each member' do
stub_memberships 'mutinerie', [
{user: {email: 'joe@doe.com'}, address: {name: 'Xavier'}, next_invoice_at: '2010-10-15', plan: {
name: 'Basic Plan', price_per_cycle_in_cents: 10050, currency: 'EUR',
extras: [{name: 'Locker', price_in_cents: 2000}]}}]
{user: {email: 'joe@doe.com'}, address: {name: 'Xavier'}, charge_taxes: true, next_invoice_at: '2010-10-15', plan: {
name: 'Basic Plan', price_per_cycle_in_cents: 10050, tax_rate: "10.00", currency: 'EUR',
extras: [{name: 'Locker', price_in_cents: 2000, tax_rate: "20"}]}}]

Timecop.travel(2010, 10, 10, 12) {
InvoiceReminderService.send_reminders
Expand All @@ -31,8 +31,8 @@
body: <<-TXT.gsub(/\s+/, ' '),
Hi Xavier.
You will be receiving an invoice for your plan Basic Plan costing
100.50 EUR in 5 days.
Extras: Locker: 20.00 EUR
110.55 EUR in 5 days.
Extras: Locker: 24.00 EUR
TXT
from: 'jane@doe.com')
end
Expand Down Expand Up @@ -62,7 +62,7 @@
expect(inbox_for('joe@doe.com')).to be_empty
end

it 'mentions other members paid for' do
it 'mentions other members paid for with old template that uses price_per_cycle' do
@reminder.update_attributes body: @reminder.body +
<<-TXT
{% if paid_for_members %}
Expand Down
18 changes: 18 additions & 0 deletions spec/models/plan_spec.rb
Expand Up @@ -12,4 +12,22 @@

expect(plan.attributes[:has_extras]).to be_false
end

it 'it applies tax if charge taxes is true' do
plan = Plan.new(price_per_cycle_in_cents: 12000, tax_rate: 10, charge_taxes: true)

expect(plan.price).to eq(132)
end

it 'it does not apply tax if charge taxes is false' do
plan = Plan.new(price_per_cycle_in_cents: 12000, tax_rate: 10, charge_taxes: nil)

expect(plan.price).to eq(120)
end

it 'it does not apply tax if charge taxes is not set' do
plan = Plan.new(price_per_cycle_in_cents: 12000)

expect(plan.price).to eq(120)
end
end