Skip to content

Commit

Permalink
project collaborators can decide tip amount of undecided tips
Browse files Browse the repository at this point in the history
  • Loading branch information
sigmike committed Mar 23, 2014
1 parent f52daf7 commit a84ce08
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -69,7 +69,7 @@ gem 'whenever'
gem 'rqrcode-rails3'
gem 'exception_notification'
gem 'rack-canonical-host'
gem 'bootstrap_forms'
gem 'bootstrap_forms', github: 'sigmike/bootstrap_forms', branch: 'sanitize_value_in_radio_label_for'

group :test do
gem 'cucumber-rails', :require => false
Expand Down
10 changes: 8 additions & 2 deletions Gemfile.lock
Expand Up @@ -26,6 +26,13 @@ GIT
rails (>= 3.1)
railties (>= 3.1)

GIT
remote: git://github.com/sigmike/bootstrap_forms.git
revision: e69b6834d36b198d36a8f4a892d1bac6633e7545
branch: sanitize_value_in_radio_label_for
specs:
bootstrap_forms (4.0.1)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -60,7 +67,6 @@ GEM
arel (4.0.2)
atomic (1.1.14)
bcrypt-ruby (3.1.2)
bootstrap_forms (4.0.1)
builder (3.1.4)
capistrano (3.0.1)
i18n
Expand Down Expand Up @@ -277,7 +283,7 @@ PLATFORMS

DEPENDENCIES
airbrake
bootstrap_forms
bootstrap_forms!
capistrano (~> 3.0)
capistrano-bundler (>= 1.1.0)
capistrano-rails
Expand Down
15 changes: 15 additions & 0 deletions app/controllers/projects_controller.rb
Expand Up @@ -28,6 +28,21 @@ def update
end
end

def decide_tip_amounts
@project = Project.find params[:id]
if request.patch?
@project.attributes = params.require(:project).permit(tips_attributes: [:id, :amount_percentage])
if @project.save
message = "The tip amounts have been defined"
if @project.has_undecided_tips?
redirect_to decide_tip_amounts_project_path(@project), notice: message
else
redirect_to @project, notice: message
end
end
end
end

def qrcode
@project = Project.find params[:id]
respond_to do |format|
Expand Down
21 changes: 12 additions & 9 deletions app/models/project.rb
@@ -1,6 +1,7 @@
class Project < ActiveRecord::Base
has_many :deposits # todo: only confirmed deposits that have amount > paid_out
has_many :tips
has_many :tips, inverse_of: :project
accepts_nested_attributes_for :tips
has_many :collaborators

validates :full_name, uniqueness: true, presence: true
Expand Down Expand Up @@ -115,13 +116,7 @@ def tip_for commit
commit: commit.sha
})

# notify user
if tip && tip.amount && user.bitcoin_address.blank? && !user.unsubscribed
if !user.notified_at || (user.notified_at < (Time.now - 30.days))
UserMailer.new_tip(user, tip).deliver
user.touch :notified_at
end
end
tip.notify_user

Rails.logger.info " Tip created #{tip.inspect}"
end
Expand Down Expand Up @@ -185,10 +180,18 @@ def update_info
end

def tips_to_pay
tips.unpaid.with_address
tips.to_pay
end

def amount_to_pay
tips_to_pay.sum(:amount)
end

def has_undecided_tips?
tips.undecided.any?
end

def commit_url(commit)
"https://github.com/#{full_name}/commit/#{commit}"
end
end
40 changes: 37 additions & 3 deletions app/models/tip.rb
@@ -1,14 +1,16 @@
class Tip < ActiveRecord::Base
belongs_to :user
belongs_to :sendmany
belongs_to :project
belongs_to :project, inverse_of: :tips

validates :amount, numericality: {greater_than: 0, allow_nil: true}
validates :amount, numericality: {greater_or_equal_than: 0, allow_nil: true}

scope :not_sent, -> { where(sendmany_id: nil) }

scope :unpaid, -> { non_refunded.not_sent }

scope :to_pay, -> { unpaid.decided.with_address }

scope :paid, -> { where('sendmany_id is not ?', nil) }

scope :refunded, -> { where('refunded_at is not ?', nil) }
Expand All @@ -21,11 +23,16 @@ class Tip < ActiveRecord::Base

scope :with_address, -> { joins(:user).where('users.bitcoin_address IS NOT NULL AND users.bitcoin_address != ?', "") }

scope :undecided, -> { where(amount: nil) }
scope :decided, -> { where.not(amount: nil) }

after_save :notify_user_if_just_decided

def paid?
!!sendmany_id
end

def amount_undecided?
def undecided?
amount.nil?
end

Expand All @@ -36,4 +43,31 @@ def self.refund_unclaimed
tip.touch :refunded_at
end
end

def commit_url
project.commit_url(commit)
end

def amount_percentage
nil
end

def amount_percentage=(percentage)
if undecided? and percentage.present?
self.amount = project.available_amount * (percentage.to_f / 100)
end
end

def notify_user
if amount and amount > 0 and user.bitcoin_address.blank? and !user.unsubscribed
if user.notified_at.nil? or user.notified_at < 30.days.ago
UserMailer.new_tip(user, self).deliver
user.touch :notified_at
end
end
end

def notify_user_if_just_decided
notify_user if amount_was.nil? and amount
end
end
25 changes: 25 additions & 0 deletions app/views/projects/decide_tip_amounts.html.haml
@@ -0,0 +1,25 @@
= bootstrap_form_for @project, url: decide_tip_amounts_project_path(@project) do |f|
%table.table
%thead
%tr
%th Commit
%th Tip (relative to the project balance)
%tbody
= f.fields_for(:tips, @project.tips.undecided) do |tip_fields|
= tip_fields.hidden_field :id
- tip = tip_fields.object
%tr
%td
= link_to tip.commit, tip.commit_url
%td
- radios = {}
- radios["Undecided"] = ""
- radios["Free: 0%"] = "0"
- radios["Tiny: 0.1%"] = "0.1"
- radios["Small: 0.5%"] = "0.5"
- radios["Normal: 1%"] = "1"
- radios["Big: 2%"] = "2"
- radios["Huge: 5%"] = "5"
= tip_fields.radio_buttons(:amount_percentage, radios, inline: true, label: false)
.text-center
= f.submit 'Send the selected tip amounts'
2 changes: 2 additions & 0 deletions app/views/projects/show.html.haml
Expand Up @@ -8,6 +8,8 @@
= @project.full_name
%small= link_to glyph(:github), @project.github_url, target: '_blank'
= link_to "Change project settings", edit_project_path(@project), class: "btn btn-default"
- if @project.has_undecided_tips?
= link_to "Decide tip amounts", decide_tip_amounts_project_path(@project), class: "btn btn-primary"

.row
.col-md-4
Expand Down
2 changes: 2 additions & 0 deletions app/views/tips/index.html.haml
Expand Up @@ -32,6 +32,8 @@
- if tip.sendmany.nil?
- if tip.refunded_at
Refunded to project's deposit
- elsif tip.undecided?
The amount of tips has not been decided yet
- elsif tip.user.bitcoin_address.blank?
User didn't specify withdrawal address
- elsif tip.project.amount_to_pay < CONFIG["min_payout"].to_d * PeercoinBalanceUpdater::COIN
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Expand Up @@ -14,6 +14,8 @@
resources :tips, :only => [:index]
member do
get :qrcode
get :decide_tip_amounts
patch :decide_tip_amounts
end
end
resources :tips, :only => [:index]
Expand Down
10 changes: 8 additions & 2 deletions features/step_definitions/common.rb
Expand Up @@ -6,6 +6,10 @@
ActionMailer::Base.deliveries.size.should eq(arg1.to_i)
end

When(/^the email counters are reset$/) do
ActionMailer::Base.deliveries.clear
end

Given(/^the tip for commit is "(.*?)"$/) do |arg1|
CONFIG["tip"] = arg1.to_f
end
Expand Down Expand Up @@ -67,11 +71,13 @@ def find_new_commit(id)
end

Then(/^there should be a tip of "(.*?)" for commit "(.*?)"$/) do |arg1, arg2|
(Tip.find_by(commit: arg2).amount.to_d / PeercoinBalanceUpdater::COIN).should eq(arg1.to_d)
amount = Tip.find_by(commit: arg2).amount
amount.should_not be_nil
(amount.to_d / PeercoinBalanceUpdater::COIN).should eq(arg1.to_d)
end

Then(/^the tip amount for commit "(.*?)" should be undecided$/) do |arg1|
Tip.find_by(commit: arg1).amount_undecided?.should be_true
Tip.find_by(commit: arg1).undecided?.should be_true
end

Then(/^the new last known commit should be "(.*?)"$/) do |arg1|
Expand Down
5 changes: 5 additions & 0 deletions features/step_definitions/tip_modifier_interface.rb
@@ -0,0 +1,5 @@
When(/^I choose the amount "(.*?)" on commit "(.*?)"$/) do |arg1, arg2|
within find("tr", text: arg2) do
choose arg1
end
end
4 changes: 4 additions & 0 deletions features/step_definitions/web.rb
Expand Up @@ -28,3 +28,7 @@
page.should have_content(arg1)
end

Then(/^I should not see "(.*?)"$/) do |arg1|
page.should have_no_content(arg1)
end

33 changes: 28 additions & 5 deletions features/tip_modifier_interface.feature
Expand Up @@ -6,13 +6,16 @@ Feature: A project collaborator can change the tips of commits
| daneel |
And our fee is "0"
And a deposit of "500"
And the last known commit is "A"
And a new commit "B" with parent "A"
And the author of commit "B" is "yugo"
And the last known commit is "AAA"
And a new commit "BBB" with parent "AAA"
And a new commit "CCC" with parent "BBB"
And the author of commit "BBB" is "yugo"
And the author of commit "CCC" is "seldon"

Scenario: Without anything modified
When the new commits are read
Then there should be a tip of "5" for commit "B"
Then there should be a tip of "5" for commit "BBB"
And there should be a tip of "4.95" for commit "CCC"
And there should be 1 email sent

Scenario: A collaborator wants to alter the tips
Expand All @@ -24,6 +27,26 @@ Feature: A project collaborator can change the tips of commits
Then I should see "The project settings have been updated"

When the new commits are read
Then the tip amount for commit "B" should be undecided
Then the tip amount for commit "BBB" should be undecided
And the tip amount for commit "CCC" should be undecided
And there should be 0 email sent

When I go to the project page
And I click on "Decide tip amounts"
Then I should see "BBB"
And I should see "CCC"
And I should not see "AAA"

When I choose the amount "Tiny: 0.1%" on commit "BBB"
And I click on "Send the selected tip amounts"
Then there should be a tip of "0.5" for commit "BBB"
And the tip amount for commit "CCC" should be undecided
And there should be 1 email sent

When the email counters are reset
And I choose the amount "Free: 0%" on commit "CCC"
And I click on "Send the selected tip amounts"
Then there should be a tip of "0.5" for commit "BBB"
And there should be a tip of "0" for commit "CCC"
And there should be 0 email sent

0 comments on commit a84ce08

Please sign in to comment.