diff --git a/Gemfile b/Gemfile index 339f0707..fd188057 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,9 @@ gem 'sidekiq', '~> 2.13.0' gem 'sinatra', require: false # required by sidekiq web interface mounted on /sidekiq # Turns every field on a editable one -gem 'best_in_place', github: 'bernat/best_in_place', branch: 'rails-4' +gem 'best_in_place', github: 'widernet/best_in_place', branch: 'rails-4' +#gem 'best_in_place', github: 'bernat/best_in_place', ref: '769ba1887feafb2b46693fe52c2953230d61c5e1' +#gem 'best_in_place', '2.1.3' # State machine for attributes on models gem 'state_machine', require: 'state_machine/core' @@ -22,15 +24,16 @@ gem 'paper_trail', github: 'airblade/paper_trail', branch: 'rails4' # Database and data related gem 'pg' -gem 'postgres-copy', github: 'josemarluedke/postgres-copy', branch: 'rails4' +gem 'postgres-copy'#, github: 'josemarluedke/postgres-copy', branch: 'rails4' gem 'pg_search' gem 'schema_plus', '~> 1.2.0' gem 'schema_associations', '~> 1.2.0' gem 'chartkick' # Payment engines -gem 'catarse_paypal_express', '~> 2.0.0' -gem 'catarse_moip', '~> 2.0.0' +#gem 'catarse_paypal_express', '~> 2.0.0' +#gem 'catarse_moip', '~> 2.0.0' +gem 'catarse_pagarme', github: 'engageis/catarse_pagarme', branch: 'v1' # # Decorators gem 'draper' @@ -55,6 +58,7 @@ gem 'catarse_mailchimp', git: 'git://github.com/catarse/catarse_mailchimp', ref: # HTML manipulation and formatting gem 'formtastic', '~> 2.2.1' +gem 'simple_form' gem "auto_html", '= 1.4.2' gem 'kaminari' @@ -135,6 +139,7 @@ end gem 'sass-rails', '~> 4.0.0' gem 'coffee-rails', '~> 4.0.0' gem "compass-rails", '~> 1.1.0' +gem 'sprockets', '2.10.0' gem 'uglifier' gem 'compass-960-plugin' diff --git a/Gemfile.lock b/Gemfile.lock index 458815d5..3faed772 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,15 +7,6 @@ GIT activerecord (~> 4.0) railties (~> 4.0) -GIT - remote: git://github.com/bernat/best_in_place.git - revision: 366413be357d65cdf47031e928aea969f72e3659 - branch: rails-4 - specs: - best_in_place (2.0.3) - jquery-rails - rails (~> 4) - GIT remote: git://github.com/catarse/catarse_mailchimp revision: 2ed4f3931dfa292e5c1c62619772f04e41c68629 @@ -35,15 +26,13 @@ GIT nokogiri (~> 1.5.0) GIT - remote: git://github.com/josemarluedke/postgres-copy.git - revision: 41afec70f5c6b2431f045388b14a80d194329a20 - branch: rails4 + remote: git://github.com/engageis/catarse_pagarme.git + revision: ff69884bbcca44795091af8b7d51218a2a66da97 + branch: v1 specs: - postgres-copy (0.6.0) - activerecord (>= 3.0.0) - pg - rails (>= 3.0.0) - responders + catarse_pagarme (1.4.8) + pagarme (~> 1.9.8) + rails (~> 4.0) GIT remote: git://github.com/ryanb/cancan.git @@ -53,6 +42,15 @@ GIT specs: cancan (2.0.0.alpha) +GIT + remote: git://github.com/widernet/best_in_place.git + revision: 964f3f36fe24cd7cd304b44f4ffac2ee1de3cd1e + branch: rails-4 + specs: + best_in_place (2.0.3) + jquery-rails + rails (~> 4) + GEM remote: https://rubygems.org/ specs: @@ -66,17 +64,6 @@ GEM erubis (~> 2.7.0) rack (~> 1.5.2) rack-test (~> 0.6.2) - active_utils (2.0.0) - activesupport (>= 2.3.11) - i18n - activemerchant (1.36.0) - active_utils (>= 1.0.2) - activesupport (>= 2.3.14) - builder (>= 2.0.0) - i18n - json (>= 1.5.1) - money - nokogiri (< 1.6.0) activemodel (4.0.0) activesupport (= 4.0.0) builder (~> 3.1.0) @@ -93,8 +80,7 @@ GEM thread_safe (~> 0.1) tzinfo (~> 0.3.37) addressable (2.3.5) - arel (4.0.0) - atomic (1.1.13) + arel (4.0.2) auto_html (1.4.2) RedCloth redcarpet @@ -116,13 +102,6 @@ GEM carrierwave (0.8.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) - catarse_moip (2.0.0) - libxml-ruby (~> 2.6.0) - rails (~> 4.0) - catarse_paypal_express (2.0.0) - activemerchant (>= 1.34.0) - rails (~> 4.0) - slim-rails celluloid (0.14.1) timers (>= 1.0.0) chartkick (1.2.0) @@ -224,7 +203,7 @@ GEM crack (= 0.1.8) httpauth (0.2.0) httpclient (2.3.4.1) - i18n (0.6.5) + i18n (0.6.11) inherited_resources (1.4.1) has_scope (~> 0.6.0.rc) responders (~> 1.0.0.rc) @@ -248,7 +227,6 @@ GEM addressable (~> 2.3) letter_opener (1.1.2) launchy (~> 2.2) - libxml-ruby (2.6.0) loofah (1.2.1) nokogiri (>= 1.4.4) mail (2.5.3) @@ -258,15 +236,14 @@ GEM mailchimp (0.0.9) httparty method_source (0.8.2) - mime-types (1.24) + mime-types (1.25.1) minitest (4.7.5) - money (5.1.1) - i18n (~> 0.6.0) - multi_json (1.7.9) + multi_json (1.10.1) multipart-post (1.2.0) net-scp (1.1.2) net-ssh (>= 2.6.5) net-ssh (2.6.8) + netrc (0.10.2) newrelic_rpm (3.6.6.147) nokogiri (1.5.10) oauth (0.4.7) @@ -291,6 +268,9 @@ GEM multi_json (~> 1.3) omniauth-oauth (~> 1.0) orm_adapter (0.4.0) + pagarme (1.9.8) + multi_json + rest-client pg (0.17.0) pg_search (0.7.0) activerecord (>= 3.1) @@ -300,7 +280,12 @@ GEM capybara (~> 2.1.0) faye-websocket (>= 0.4.4, < 0.5.0) http_parser.rb (~> 0.5.3) - polyglot (0.3.3) + polyglot (0.3.5) + postgres-copy (0.9.0) + activerecord (>= 4.0) + pg (>= 0.17) + rails (>= 4.0) + responders protected_attributes (1.0.3) activemodel (>= 4.0.0, < 5.0) pry (0.9.12.2) @@ -336,7 +321,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) raindrops (0.11.0) - rake (10.1.0) + rake (10.4.2) ranked-model (0.3) activerecord (>= 3.1.12) redcarpet (3.0.0) @@ -346,8 +331,9 @@ GEM request_store (1.0.5) responders (1.0.0.rc) railties (>= 3.2, < 5) - rest-client (1.6.7) - mime-types (>= 1.16) + rest-client (1.7.2) + mime-types (>= 1.16, < 3.0) + netrc (~> 0.7) rinku (1.7.3) rmagick (2.13.2) routing-filter (0.4.0.pre) @@ -398,6 +384,9 @@ GEM json redis (>= 3.0) redis-namespace + simple_form (3.0.0) + actionpack (>= 4.0.0, < 4.1) + activemodel (>= 4.0.0, < 4.1) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) @@ -431,15 +420,176 @@ GEM activemodel (>= 3.0.0.beta) tag_helper (0.0.3) temple (0.6.6) - thor (0.18.1) - thread_safe (0.1.2) - atomic + thor (0.19.1) + thread_safe (0.3.4) tilt (1.4.1) timers (1.1.0) - treetop (1.4.14) + treetop (1.4.15) + polyglot polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) + polyglot (>= 0.3.1) polyglot (>= 0.3.1) - tzinfo (0.3.37) + tzinfo (0.3.42) uglifier (2.1.2) execjs (>= 0.3.0) multi_json (~> 1.0, >= 1.0.2) @@ -471,8 +621,7 @@ DEPENDENCIES capybara (~> 2.1.0) carrierwave (~> 0.8.0) catarse_mailchimp! - catarse_moip (~> 2.0.0) - catarse_paypal_express (~> 2.0.0) + catarse_pagarme! chartkick coffee-rails (~> 4.0.0) compass-960-plugin @@ -510,7 +659,7 @@ DEPENDENCIES pg pg_search poltergeist - postgres-copy! + postgres-copy protected_attributes (~> 1.0.3) pry rack-timeout @@ -528,9 +677,11 @@ DEPENDENCIES selenium-webdriver (~> 2.34.0) shoulda sidekiq (~> 2.13.0) + simple_form sinatra slim-rails (~> 1.1.1) spectator-validates_email + sprockets (= 2.10.0) state_machine uglifier unicorn diff --git a/app/assets/javascripts/app/user.js b/app/assets/javascripts/app/user.js index 815a4220..e185210a 100644 --- a/app/assets/javascripts/app/user.js +++ b/app/assets/javascripts/app/user.js @@ -12,6 +12,7 @@ App.addChild('User', _.extend({ this.makeRoute('credits'); this.makeRoute('settings'); this.makeRoute('unsubscribes'); + this.makeRoute('credit_cards'); }, makeRoute: function(name){ diff --git a/app/assets/javascripts/lib/jquery.brbanks.js b/app/assets/javascripts/lib/jquery.brbanks.js new file mode 100644 index 00000000..45bfcc8f --- /dev/null +++ b/app/assets/javascripts/lib/jquery.brbanks.js @@ -0,0 +1,103 @@ +(function($){ + $.fn.extend({ + brbanks: function(options) { + var root = this; + + local = { + selector: this, + bankDivSelector: '.brbanks-banks', + banks: [], + + parseToList: function(banks_data) { + that = this; + $.each(banks_data, function(i,item){ + that.banks.push(item.id + ' - ' + item.name) + }); + + that.inserListOnData(); + }, + + inserListOnData: function() { + this.selector.data('banks', this.banks); + }, + + loadBanksOnSelector: function(callback) { + var that = this; + $.getJSON("http://brbanks.herokuapp.com", function(data){ + that.parseToList(data); + callback(that); + }); + }, + + buildBankDiv: function() { + var div = $("") + var ul = $("") + + $.each(this.selector.data('banks'), function(i, item){ + ul.append($('
  • '+item+'
  • ')); + }); + + div.prepend(ul); + return div; + } + } + + showUpBanks = function(that) { + that.selector.focusin(function(){ + if($(that.bankDivSelector).length <= 0) { + var div = that.buildBankDiv(); + that.selector.parent().append(div); + div.show(); + } else { + $(that.bankDivSelector).show(); + }; + + $('ul li', that.bankDivSelector).click(function(element){ + root.val($(element.currentTarget).text()); + $(that.bankDivSelector).hide(); + }) + }); + + $(document).mouseup(function(e){ + if(!$(that.bankDivSelector).is(e.target) && !that.selector.is(e.target)) { + $(that.bankDivSelector).hide(); + $('ul li', that.bankDivSelector).css({display: 'block'}); + + if($.inArray($(that.selector).val(), that.banks) < 0) { + $(that.selector).val(''); + }; + } + }); + }; + + enableFilterOnBanks = function(that) { + that.selector.keyup(function(){ + var value = that.selector.val(); + var regexPattern = new RegExp(value, 'i'); + + $('ul li', that.bankDivSelector).filter(function(){ + if(regexPattern.test($(this).text())) { + $(this).fadeIn(); + } else { + $(this).css({'display':'none'}); + $(this).fadeOut(); + } + }); + //$.each($('ul li', that.bankDivSelector), function(i, item){ + // if(regexPattern.test($(item).text())){ + // $(item).css({'display':'block'}) + // } else { + // $(item).css({'display':'none'}) + // } + //}); + }); + }; + + local.loadBanksOnSelector(function(that) { + showUpBanks(that); + enableFilterOnBanks(that); + }); + } + }); +})(jQuery); + diff --git a/app/assets/stylesheets/miv/_index.sass b/app/assets/stylesheets/miv/_index.sass index 6cb8872d..8ef65baf 100644 --- a/app/assets/stylesheets/miv/_index.sass +++ b/app/assets/stylesheets/miv/_index.sass @@ -34,7 +34,7 @@ +box-shadow(rgba(black,0.75) 0px 0px 5px inset !important) &:active +box-shadow(rgba(black, 1) 0px 0px 15px inset !important) - + #announcement display: block padding: 10px @@ -148,4 +148,50 @@ span.on_the_spot_editing .avatar_wrapper overflow: hidden - +.brbanks-banks + margin: 0 !important + padding: 5px !important + position: absolute + width: 260px + max-height: 200px + overflow: auto + background: white + border: #dfdfdf 1px solid + border-radius: 4px + ul + padding: 0 !important + margin: 0 !important + list-style-position: inside + list-style-type: none + li + margin: 0 !important + font-size: 12px !important + padding: 5px 0 + &:hover + background: #ededed +.bank_accounts + .input, .inputs + float: left + width: 160px + #user_bank_account_attributes_agency_input, .user_bank_account_agency + width: 60px + input[type='text'] + width: 40px + #user_bank_account_attributes_agency_digit_input, .user_bank_account_agency_digit + width: 60px + input[type='text'] + width: 40px + #user_bank_account_attributes_name_input, .user_bank_account_name + width: 220px + input[type='text'] + width: 200px + #user_bank_account_attributes_account_input, .user_bank_account_account + width: 150px + input[type='text'] + width: 130px + #user_bank_account_attributes_account_digit_input, .user_bank_account_account_digit + width: 60px + input[type='text'] + width: 40px + input[type='text'] + width: 140px diff --git a/app/assets/stylesheets/resources/backers/_create.sass b/app/assets/stylesheets/resources/backers/_create.sass index 931c080a..8155844f 100644 --- a/app/assets/stylesheets/resources/backers/_create.sass +++ b/app/assets/stylesheets/resources/backers/_create.sass @@ -430,3 +430,34 @@ text-decoration: none &:hover text-decoration: underline + .save_card + input[type='checkbox'] + float: left + margin-right: 10px + label + float: left + ul.my_credit_cards + list-style-position: none + list-style-type: none + width: 100% + li + width: 90% + display: block + padding: 10px 10px 5px + border: 1px solid #DFDFDF + background: #F4F4F4 + .radio_button + float: left + width: 5% + .select_installments + float: left + width: 30% + select + width: 90% + .card_info + float: left + width: 40% + margin-left: 10px + .card_brand + float: left + width: 10% diff --git a/app/controllers/users/credit_cards_controller.rb b/app/controllers/users/credit_cards_controller.rb new file mode 100644 index 00000000..c8bffd2a --- /dev/null +++ b/app/controllers/users/credit_cards_controller.rb @@ -0,0 +1,11 @@ +class Users::CreditCardsController < ApplicationController + load_and_authorize_resource + inherit_resources + actions :destroy + belongs_to :user + + def destroy + resource.cancel_subscription + destroy! { user_path(parent, anchor: 'credit_cards') } + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e9289049..945112c3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -20,6 +20,8 @@ def show @credits = @user.backs.can_refund @subscribed_to_updates = @user.updates_subscription @unsubscribes = @user.project_unsubscribes + @credit_cards = @user.credit_cards + build_bank_account } end @@ -74,4 +76,9 @@ def credits @credits = @user.backs.can_refund.order(:id).all render json: @credits end + + private + def build_bank_account + @user.build_bank_account unless @user.bank_account + end end diff --git a/app/decorators/credit_card_decorator.rb b/app/decorators/credit_card_decorator.rb new file mode 100644 index 00000000..527c9c4b --- /dev/null +++ b/app/decorators/credit_card_decorator.rb @@ -0,0 +1,8 @@ +class CreditCardDecorator < Draper::Decorator + decorates :credit_card + include Draper::LazyHelpers + + def display_digits + "XXXX-XXXX-XXXX-#{source.last_digits}" + end +end diff --git a/app/models/ability.rb b/app/models/ability.rb index 302427d1..51aee2ee 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -26,6 +26,11 @@ def initialize(current_user, options = {}) project.user == current_user && ( project.draft? || project.rejected? ) end + # NOTE: Credit card authorizations + can :access, :credit_cards do |credit_card| + credit_card.user == current_user + end + # NOTE: Reward authorizations can :create, :rewards do |reward| diff --git a/app/models/bank.rb b/app/models/bank.rb new file mode 100644 index 00000000..de36a007 --- /dev/null +++ b/app/models/bank.rb @@ -0,0 +1,20 @@ +class Bank < ActiveRecord::Base + has_many :bank_accounts + + validates :name, :code, presence: true + scope :order_popular, ->{ + select('banks.code, banks.id, banks.name, count(bank_accounts.bank_id) as total'). + joins('left join bank_accounts on bank_accounts.bank_id = banks.id'). + group('banks.id, bank_accounts.bank_id').order('total DESC') + } + + def self.to_collection + order_popular.map do |bank| + [bank.to_s, bank.id] + end + end + + def to_s + [code, name].join(' . ') + end +end diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb new file mode 100644 index 00000000..34a0d0ff --- /dev/null +++ b/app/models/bank_account.rb @@ -0,0 +1,13 @@ +class BankAccount < ActiveRecord::Base + #include CatarsePagarme::BankAccountConcern + + belongs_to :user + belongs_to :bank + + validates :bank_id, :agency, :account, :owner_name, :owner_document, :account_digit, presence: true + + def bank_code + self.bank.code + end +end + diff --git a/app/models/credit_card.rb b/app/models/credit_card.rb new file mode 100644 index 00000000..8459eec4 --- /dev/null +++ b/app/models/credit_card.rb @@ -0,0 +1,17 @@ +class CreditCard < ActiveRecord::Base + belongs_to :user + + validates :user, :last_digits, :card_brand, :subscription_id, presence: true + delegate :display_digits, to: :decorator + + def decorator + CreditCardDecorator.new(self) + end + + def cancel_subscription + if defined?(CatarsePagarme) + self.pagarme_delegator.cancel_subscription + end + end +end + diff --git a/app/models/user.rb b/app/models/user.rb index 589c3bd7..1ae54be4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -52,7 +52,8 @@ class User < ActiveRecord::Base :twitter, :facebook_link, :other_link, - :moip_login + :moip_login, + :bank_account_attributes mount_uploader :uploaded_image, UserUploader @@ -69,7 +70,9 @@ class User < ActiveRecord::Base schema_associations has_many :oauth_providers, through: :authorizations has_many :backs, class_name: "Backer" + has_many :credit_cards has_one :user_total + has_one :bank_account has_and_belongs_to_many :recommended_projects, join_table: :recommendations, class_name: 'Project' @@ -80,6 +83,7 @@ class User < ActiveRecord::Base has_many :channels_subscribers accepts_nested_attributes_for :unsubscribes, allow_destroy: true rescue puts "No association found for name 'unsubscribes'. Has it been defined yet?" + accepts_nested_attributes_for :bank_account, allow_destroy: true scope :backers, -> { where("id IN ( diff --git a/app/views/projects/backers/create.html.slim b/app/views/projects/backers/create.html.slim index 2f9a973a..182e9c69 100644 --- a/app/views/projects/backers/create.html.slim +++ b/app/views/projects/backers/create.html.slim @@ -1,6 +1,8 @@ #page_content .container #project_review data-thank-you-path=project_backer_path(project_id: @project.id, id: @backer.id) + = hidden_field_tag :contribution_id, @backer.id + = hidden_field_tag :project_id, @project.id .project_info = image_tag @project.display_image, id: 'project_image', alt: @project.name, width: '250px' h1= t('.you_are_about_html', link: link_to(@project.name, project_by_slug_path(permalink: @project.permalink))) @@ -65,10 +67,10 @@ .tab_container nav#payment_menu - PaymentEngines.engines.each do |engine| - - unless engine[:name] == 'moip' - = link_to "##{engine[:name]}_payment", id: engine[:name], class: 'selected enabled' , data: {target: "##{engine[:name]}_payment"} do - = t("projects.backers.review.#{engine[:name]}") + - unless engine.name == 'moip' + = link_to "##{engine.name}_payment", id: engine.name, class: 'selected enabled' , data: {target: "##{engine.name}_payment"} do + = t("projects.backers.review.#{engine.name}") .tab_content_container - PaymentEngines.engines.each do |engine| - div[id="#{engine[:name]}_payment" class="payments_type hide" data-path=engine[:review_path].call(@backer) ] + div[id="#{engine.name}_payment" class="payments_type hide" data-path=engine.review_path(@backer) ] .clearfix diff --git a/app/views/users/_credit_cards.html.slim b/app/views/users/_credit_cards.html.slim new file mode 100644 index 00000000..e248e616 --- /dev/null +++ b/app/views/users/_credit_cards.html.slim @@ -0,0 +1,13 @@ +.table_content + table.table.table-striped + thead + th= t('.index.last_digits') + th= t('.index.brand') + th + - @credit_cards.each do |card| + tr + td.card_name= card.display_digits + td.brand= card.card_brand + td.actions + .bootstrap-twitter + = link_to t('.index.remove'), user_credit_card_path(@user, card), class: 'btn btn-danger', method: :delete, data: { confirm: 'você tem certeza?' } diff --git a/app/views/users/_current_user_fields.html.slim b/app/views/users/_current_user_fields.html.slim index bee3ca3b..d709312e 100644 --- a/app/views/users/_current_user_fields.html.slim +++ b/app/views/users/_current_user_fields.html.slim @@ -1,3 +1,25 @@ +#bank_account.user_data + h1= t('.bank_account_title') + br/ + ul + li + .bootstrap-form + = semantic_form_for @user, html: {method: :put, id: 'user_form'} do |f| + .bank_accounts + = f.semantic_fields_for :bank_account do |bank_form| + = bank_form.input :bank_id, as: :select, collection: Bank.to_collection + .clearfix + = bank_form.input :agency, as: :string + = bank_form.input :agency_digit, as: :string + .clearfix + = bank_form.input :account, as: :string + = bank_form.input :account_digit, as: :string + .clearfix + = bank_form.input :owner_name, as: :string, input_html: { value: bank_form.object.owner_name || @user.full_name } + = bank_form.input :owner_document, as: :string, input_html: { value: bank_form.object.owner_document || @user.cpf } + .clearfix + .bootstrap-twitter + p= f.submit t('.update_social_info'), class: 'btn' #my_avatar h1 = t('.local_avatar') ul diff --git a/app/views/users/show.html.slim b/app/views/users/show.html.slim index 5873108c..95d067ea 100644 --- a/app/views/users/show.html.slim +++ b/app/views/users/show.html.slim @@ -41,6 +41,8 @@ = link_to t('.tabs.credits'), '#credits', id: 'credits_link', data: { target: '#user_credits' } = link_to t('.tabs.settings'), '#settings', id: 'settings_link', data: { target: '#user_settings' } = link_to t('.tabs.unsubscribes'), '#unsubscribes', id: 'unsubscribes_link', data: { target: '#user_unsubscribes' } + - if @credit_cards.present? + = link_to t('.tabs.credit_cards'), '#credit_cards', id: 'credit_cards_link', data: { target: '#user_credit_cards' } .clearfix #user_profile_content #user_backed_projects.content[data-path=user_backers_path(@user)] @@ -68,5 +70,10 @@ = render 'current_user_fields' #user_credits.content.hide = render 'credits' + - if @credit_cards.present? + #user_credit_cards.content.hide + = render 'credit_cards' + + .clearfix .clearfix diff --git a/config/initializers/pagarme.rb b/config/initializers/pagarme.rb new file mode 100644 index 00000000..e5f6051a --- /dev/null +++ b/config/initializers/pagarme.rb @@ -0,0 +1,12 @@ +CatarsePagarme.configure do |config| + config.api_key = Configuration[:pagarme_api_key] + config.slip_tax = Configuration[:pagarme_slip_tax] + config.credit_card_tax = Configuration[:pagarme_credit_card_tax] + config.interest_rate = Configuration[:pagarme_interest_rate] + config.credit_card_cents_fee = Configuration[:pagarme_cents_fee] + config.host = Configuration[:host] + config.subdomain = 'www' + config.protocol = 'http' + config.max_installments = Configuration[:pagarme_max_installments] + config.minimum_value_for_installment = Configuration[:pagarme_minimum_value_for_installment] +end diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 7a3727de..2e17b7e0 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -177,11 +177,21 @@ pt: password: Senha password_confirmation: "Confirmação de senha" phone_number: "Telefone (fixo ou celular)" + bank_account: + bank: 'Banco' + bank_id: 'Banco' + owner_name: 'Nome do titular' + owner_document: 'CPF / CNPJ do titular' + agency: 'Agência' + agency_digit: 'Dígito' + account: 'Número da conta' + account_digit: 'Dígito' models: backer: Apoiador category: Categoria project: Projeto reward: Recompensa + bank_account: Dados bancários backer: display_confirmed_at: "Há %{time_ago}" reward_must_be_from_project: "deve ser do mesmo projeto" @@ -396,6 +406,60 @@ pt: draft: "Esse projeto é apenas um rascunho e ainda não está aberto para receber apoios." reached_of: "Atingidos de" submit: "Apoiar este projeto" + contributions: + review: + Credits: 'Créditos' + error: Ooops. Ocorreu um erro ao registrar seu apoio. Por favor, tente novamente. + form: + labels: + payment_boleto: Pagamento com Boleto + payment_card: Pagamento com Cartão + submit: Efetuar pagamento + build_boleto: Gerar boleto + payment_boleto_subtitle: "Clique no link abaixo para ver o boleto:" + edit: + form_labels: + payment_card_number: 'Número do cartão de crédito' + payment_card_flag: 'Bandeira' + payment_card_source: 'Código de Segurança' + payment_card_date: 'Data de Expiração' + payment_card_name: 'Nome impresso no cartão de crédito' + payment_card_installments: 'Parcelas' + installment_with_tax: 'sem juros' + transaction_error: 'Transação recusada, por favor verifique novamente seus dados ou entre em contato com o banco/emissor do cartão para maiores informações.' + pagarme_warning_html: "O Catarse está em fase de teste de um novo meio de pagamento que facilitará o apoio financeiro e o eventual reembolso dos valores aos apoiadores. Dessa forma, alertamos que poderão ser exigidos dados extras, além daqueles mencionados nos Termos de Uso para apoiar este projeto. Qualquer dúvida ou dificuldade, entre em contato conosco pelo e-mail %{mailto} . Obrigado." + payment_save_card: 'Quero salvar meu cartão de crédito para facilitar apoios futuros.' + reward_sold_out: Essa recompensa está esgotada. Inicie um novo apoio. + credits_preview_html: "Você possui %{credits} em créditos para realizar esse apoio até o dia 10/11, conforme novas regras divulgadas pelo Catarse." + credits_submit: 'Efetuar pagamento' + credits_title: 'Pagamento com créditos' + insufficient_credits: "Você possui %{credits} em créditos. Esse valor não é suficiente para realizar o apoio, por favor escolha outro meio de pagamento." + choose_payment: Como você quer pagar? + choose_payment_subtitle: Selecione abaixo uma forma de pagamento + cpf: 'Para prosseguir, por favor informe:' + credits_notice_html: Este apoio será pago com seus créditos. Após a confirmação, + você ficará com um saldo de %{credits} em créditos para + apoiar outros projetos. + live_in_brazil: Moro no Brasil. ( Desmarque caso o seu apoio seja internacional + ) + number_card: Dados do cartão + owner_card: Dados do titular do cartão + payment_account: Pagamento com Débito em Conta + payment_boleto: Pagamento com Boleto + payment_card: Pagamento com Cartão + review_with_reward_html: 'Você irá apoiar com %{value} e + ganhará a seguinte recompensa:' + review_without_reward_html: Você irá apoiar com %{value} + e não quer nenhuma recompensa por seu apoio. + select_account: 'Você será redirecionado para o site do seu banco:' + select_boleto: 'Para prosseguir, por favor selecione:' + submit: + credits: Confirmar + moip: Efetuar pagamento pelo MoIP + subtitle: Estes dados serão informados ao organizador do projeto. + title: Preencha e revise os dados para pagamento + you_are_about_html: Você está prestes a fazer parte do grupo que faz de tudo + para o %{link} acontecer. backers: backer: anonymous_backer: "Apoiador anônimo" @@ -813,9 +877,16 @@ pt: site_title: 'Defina um email de contato' title: 'Defina um email de contato' submit: 'Gravar o email e prosseguir' + credit_cards: + index: + last_digits: 'Cartão' + brand: 'Operadora' + title: 'Cartões de credito' + remove: 'Remover' show: attention: "Atenção" tabs: + credit_cards: "Cartões de credito" backed_projects: "Projetos apoiados" created_projects: "Projetos criados" comments: Comentários @@ -838,6 +909,8 @@ pt: title: "Escolha de quais projetos você deseja receber notificações:" updates: "Eu quero receber atualizações dos projetos" current_user_fields: + bank_account_title: "Dados bancários" + bank_account_hint: "Seus dados bancários serão utilizados para realizar o reembolso integral do seu apoio, caso o projeto não atinja 100% da meta estabelecida." my_facebook: 'Integração com o facebook' bio_limit: 'até 140 caracteres' updated: "As suas informações foram atualizadas" diff --git a/config/routes.rb b/config/routes.rb index 7f22f2fe..bf8f802c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,8 +24,9 @@ mount Sidekiq::Web => '/sidekiq' end - mount CatarsePaypalExpress::Engine => "/", as: :catarse_paypal_express - mount CatarseMoip::Engine => "/", as: :catarse_moip + #mount CatarsePaypalExpress::Engine => "/", as: :catarse_paypal_express + #mount CatarseMoip::Engine => "/", as: :catarse_moip + mount CatarsePagarme::Engine => "/", as: :catarse_pagarme # Non production routes if Rails.env.development? @@ -102,6 +103,7 @@ end resources :users do resources :projects, controller: 'users/projects', only: [ :index ] + resources :credit_cards, controller: 'users/credit_cards', only: [ :destroy ] collection do get :uservoice_gadget end diff --git a/db/migrate/20141211124556_create_bank_accounts.rb b/db/migrate/20141211124556_create_bank_accounts.rb new file mode 100644 index 00000000..58e81226 --- /dev/null +++ b/db/migrate/20141211124556_create_bank_accounts.rb @@ -0,0 +1,17 @@ +class CreateBankAccounts < ActiveRecord::Migration + def change + create_table :bank_accounts do |t| + t.references :user, index: true + t.text :name, null: false + t.text :account, null: false + t.text :account_digit + t.text :agency, null: false + t.text :agency_digit + t.text :owner_name, null: false + t.text :owner_document, null: false + + t.timestamps + t.timestamps + end + end +end diff --git a/db/migrate/20141211125209_create_banks.rb b/db/migrate/20141211125209_create_banks.rb new file mode 100644 index 00000000..645c496c --- /dev/null +++ b/db/migrate/20141211125209_create_banks.rb @@ -0,0 +1,11 @@ +class CreateBanks < ActiveRecord::Migration + def change + create_table :banks do |t| + t.text :name, null: false + t.text :code, null: false + + t.timestamps + end + add_index :banks, :code, unique: true + end +end diff --git a/db/migrate/20141211125359_add_bank_into_bank_accounts.rb b/db/migrate/20141211125359_add_bank_into_bank_accounts.rb new file mode 100644 index 00000000..9e0ed39a --- /dev/null +++ b/db/migrate/20141211125359_add_bank_into_bank_accounts.rb @@ -0,0 +1,5 @@ +class AddBankIntoBankAccounts < ActiveRecord::Migration + def change + add_column :bank_accounts, :bank_id, :integer, index: true + end +end diff --git a/db/migrate/20141211130230_change_remove_name_from_bank_accounts.rb b/db/migrate/20141211130230_change_remove_name_from_bank_accounts.rb new file mode 100644 index 00000000..3658991f --- /dev/null +++ b/db/migrate/20141211130230_change_remove_name_from_bank_accounts.rb @@ -0,0 +1,5 @@ +class ChangeRemoveNameFromBankAccounts < ActiveRecord::Migration + def change + remove_column :bank_accounts, :name + end +end diff --git a/db/migrate/20141211134156_insert_banks.rb b/db/migrate/20141211134156_insert_banks.rb new file mode 100644 index 00000000..e7c244d0 --- /dev/null +++ b/db/migrate/20141211134156_insert_banks.rb @@ -0,0 +1,148 @@ +class InsertBanks < ActiveRecord::Migration + def up + execute <