spree_zaez_komerci 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +9 -0
  6. data/Guardfile +90 -0
  7. data/LICENSE +26 -0
  8. data/README.md +52 -0
  9. data/Rakefile +21 -0
  10. data/app/assets/images/rede-credit-cards/rede-dinersclub.png +0 -0
  11. data/app/assets/images/rede-credit-cards/rede-hipercard.png +0 -0
  12. data/app/assets/images/rede-credit-cards/rede-jcb.png +0 -0
  13. data/app/assets/images/rede-credit-cards/rede-mastercard.png +0 -0
  14. data/app/assets/images/rede-credit-cards/rede-visa.png +0 -0
  15. data/app/assets/javascripts/spree/backend/spree_zaez_komerci.js +1 -0
  16. data/app/assets/javascripts/spree/frontend/app/komerci_credit_card.js.coffee +26 -0
  17. data/app/assets/javascripts/spree/frontend/spree_zaez_komerci.js +1 -0
  18. data/app/assets/stylesheets/spree/frontend/spree_zaez_komerci.css +7 -0
  19. data/app/controllers/spree/admin/komerci_settings_controller.rb +20 -0
  20. data/app/models/spree/credit_card_decorator.rb +7 -0
  21. data/app/models/spree/komerci_transaction.rb +8 -0
  22. data/app/models/spree/payment/gateway_options_decorator.rb +14 -0
  23. data/app/models/spree/payment_method/komerci.rb +250 -0
  24. data/app/overrides/spree/admin/shared/sub_menu/_configuration/add_komerci_settings_to_configuration_tab.html.erb.deface +2 -0
  25. data/app/views/spree/admin/komerci_settings/edit.html.erb +67 -0
  26. data/app/views/spree/admin/payments/source_forms/_komerci.html.erb +62 -0
  27. data/app/views/spree/admin/payments/source_views/_komerci.html.erb +33 -0
  28. data/app/views/spree/checkout/payment/_komerci.html.erb +62 -0
  29. data/bin/rails +7 -0
  30. data/config/locales/en.yml +31 -0
  31. data/config/locales/pt-br.yml +32 -0
  32. data/config/routes.rb +5 -0
  33. data/db/migrate/20160630132716_add_portions_to_spree_payments.rb +5 -0
  34. data/db/migrate/20160630161016_create_spree_komerci_transaction.rb +14 -0
  35. data/db/migrate/20160701184408_add_payment_id_to_spree_komerci_transactions.rb +5 -0
  36. data/db/migrate/20160704120859_add_total_to_spree_komerci_transactions.rb +5 -0
  37. data/lib/generators/spree_zaez_komerci/install/install_generator.rb +30 -0
  38. data/lib/spree/komerci_configuration.rb +190 -0
  39. data/lib/spree_zaez_komerci/engine.rb +30 -0
  40. data/lib/spree_zaez_komerci/factories.rb +30 -0
  41. data/lib/spree_zaez_komerci.rb +5 -0
  42. data/spec/features/admin/komerci_actions_spec.rb +80 -0
  43. data/spec/features/admin/komerci_settings_spec.rb +77 -0
  44. data/spec/features/checkout_with_komerci_spec.rb +75 -0
  45. data/spec/fixtures/authorize_error.txt +14 -0
  46. data/spec/fixtures/authorize_success.txt +14 -0
  47. data/spec/fixtures/conf_authorize_error.txt +7 -0
  48. data/spec/fixtures/conf_authorize_success.txt +7 -0
  49. data/spec/fixtures/error.txt +1 -0
  50. data/spec/fixtures/void_error.txt +7 -0
  51. data/spec/fixtures/void_success.txt +7 -0
  52. data/spec/lib/spree/komerci_configuration_spec.rb +82 -0
  53. data/spec/models/spree/payment_method/komerci_spec.rb +206 -0
  54. data/spec/spec_helper.rb +99 -0
  55. data/spec/support/capybara_login.rb +11 -0
  56. data/spec/support/shared_contexts/checkout_setup.rb +9 -0
  57. data/spree_zaez_komerci.gemspec +42 -0
  58. data/vendor/assets/javascripts/jquery.payment.js +612 -0
  59. metadata +423 -0
@@ -0,0 +1,62 @@
1
+ <div class="well clearfix">
2
+ <% param_prefix = "payment_source[#{payment_method.id}]" %>
3
+
4
+ <div class="row">
5
+ <div class="col-md-12 field">
6
+ <%= label_tag "name_on_card_#{payment_method.id}", Spree.t(:name_on_card) %><span class="required">*</span><br />
7
+ <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}",
8
+ { id: "name_on_card_#{payment_method.id}", class: 'form-control required'} %>
9
+ </div>
10
+ <div class="col-md-12 field">
11
+ <%= label_tag 'card_number', Spree.t(:card_number) %><span class="required">*</span><br />
12
+ <% options_hash = Rails.env.production? ? {:autocomplete => 'off'} : {} %>
13
+ <%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(id: 'cielo_card_number',
14
+ class: 'form-control required cardNumber komerci-cc',
15
+ size: 19,
16
+ maxlength: 19,
17
+ autocomplete: 'off') %>
18
+ <span id="komerci_unrecognized" style="display:none;" class="error"><%= Spree.t(:unrecognized_card_type) %></span>
19
+ </div>
20
+ </div>
21
+ <div class="row">
22
+ <div class="col-md-8 field" data-hook="card_expiration">
23
+ <%= label_tag 'card_expiry', Spree.t(:expiration) %><span class="required">*</span><br />
24
+ <%= text_field_tag "#{param_prefix}[expiry]", '', id: 'card_expiry',
25
+ class: 'form-control required cardExpiry', placeholder: 'MM / YY' %>
26
+ </div>
27
+ <div class="col-md-4 field" data-hook="card_code">
28
+ <%= label_tag 'card_code', Spree.t(:card_code) %><span class="required">*</span><br />
29
+ <%= text_field_tag "#{param_prefix}[verification_value]", '', options_hash.merge(id: 'card_code',
30
+ class: 'form-control required cardCode',
31
+ size: 5) %>
32
+ </div>
33
+ </div>
34
+ <div class="row komerci-info">
35
+ <% portions = Spree::KomerciConfig.calculate_portions @order %>
36
+ <div class="col-sm-10">
37
+ <% portions.each do |item| %>
38
+ <%
39
+ total = Spree::Money.new(item[:total], {currency: @order.currency}).to_html
40
+ value = Spree::Money.new(item[:value], {currency: @order.currency}).to_html
41
+ %>
42
+ <%= radio_button_tag 'order[payments_attributes][][portions]', item[:portion], item[:portion] == 1 %>
43
+ <%= Spree.t(:komerci_portions, times: item[:portion], value: value,
44
+ tax: Spree.t(item[:tax_message]), total: total) %><br />
45
+ <% end %>
46
+ </div>
47
+ <div class="col-sm-2" id="komerci_cc_type"></div>
48
+ </div>
49
+
50
+ <%= hidden_field_tag "#{param_prefix}[cc_type]", '', id: 'cc_type' %>
51
+ </div>
52
+
53
+ <script type="text/javascript">
54
+ available_cc = {
55
+ visa: '<%= asset_url 'rede-credit-cards/rede-visa.png' %>',
56
+ mastercard: '<%= asset_url 'rede-credit-cards/rede-mastercard.png' %>',
57
+ dinersclub: '<%= asset_url 'rede-credit-cards/rede-dinersclub.png' %>',
58
+ hipercard: '<%= asset_url 'rede-credit-cards/rede-hipercard.png' %>',
59
+ jcb: '<%= asset_url 'rede-credit-cards/rede-jcb.png' %>'
60
+ };
61
+ new window.KomerciCreditCard(available_cc);
62
+ </script>
@@ -0,0 +1,33 @@
1
+ <fieldset data-hook="credit_card">
2
+ <legend><%= Spree.t(:credit_card) %></legend>
3
+ <table class="table table-condensed table-bordered">
4
+ <tr>
5
+ <th width="20%"><%= Spree.t(:name_on_card) %>:</th>
6
+ <td><%= payment.source.name %></td>
7
+ </tr>
8
+ <tr>
9
+ <th><%= Spree.t(:card_type) %>:</th>
10
+ <td><%= payment.source.cc_type %></td>
11
+ </tr>
12
+ <tr>
13
+ <th><%= Spree.t(:card_number) %>:</th>
14
+ <td><%= payment.source.display_number %></td>
15
+ </tr>
16
+ <tr>
17
+ <th><%= Spree.t(:expiration) %>:</th>
18
+ <td><%= payment.source.month %>/<%= payment.source.year %></td>
19
+ </tr>
20
+ <tr>
21
+ <th><%= Spree.t(:portions) %>:</th>
22
+ <td><%= "#{payment.portions}x" %></td>
23
+ </tr>
24
+ <tr>
25
+ <th><%= Spree.t(:transaction_id) %>:</th>
26
+ <td><%= payment.transaction_id %></td>
27
+ </tr>
28
+ <tr>
29
+ <th><%= Spree.t(:number) %>:</th>
30
+ <td><%= "#{payment.order.number}-#{payment.id}" %></td>
31
+ </tr>
32
+ </table>
33
+ </fieldset>
@@ -0,0 +1,62 @@
1
+ <div class="well clearfix">
2
+ <% param_prefix = "payment_source[#{payment_method.id}]" %>
3
+
4
+ <div class="row">
5
+ <div class="col-md-12 field">
6
+ <%= label_tag "name_on_card_#{payment_method.id}", Spree.t(:name_on_card) %><span class="required">*</span><br />
7
+ <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}",
8
+ { id: "name_on_card_#{payment_method.id}", class: 'form-control required'} %>
9
+ </div>
10
+ <div class="col-md-12 field">
11
+ <%= label_tag 'card_number', Spree.t(:card_number) %><span class="required">*</span><br />
12
+ <% options_hash = Rails.env.production? ? {:autocomplete => 'off'} : {} %>
13
+ <%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(id: 'cielo_card_number',
14
+ class: 'form-control required cardNumber komerci-cc',
15
+ size: 19,
16
+ maxlength: 19,
17
+ autocomplete: 'off') %>
18
+ <span id="komerci_unrecognized" style="display:none;" class="error"><%= Spree.t(:unrecognized_card_type) %></span>
19
+ </div>
20
+ </div>
21
+ <div class="row">
22
+ <div class="col-md-8 field" data-hook="card_expiration">
23
+ <%= label_tag 'card_expiry', Spree.t(:expiration) %><span class="required">*</span><br />
24
+ <%= text_field_tag "#{param_prefix}[expiry]", '', id: 'card_expiry',
25
+ class: 'form-control required cardExpiry', placeholder: 'MM / YY' %>
26
+ </div>
27
+ <div class="col-md-4 field" data-hook="card_code">
28
+ <%= label_tag 'card_code', Spree.t(:card_code) %><span class="required">*</span><br />
29
+ <%= text_field_tag "#{param_prefix}[verification_value]", '', options_hash.merge(id: 'card_code',
30
+ class: 'form-control required cardCode',
31
+ size: 5) %>
32
+ </div>
33
+ </div>
34
+ <div class="row komerci-info">
35
+ <% portions = Spree::KomerciConfig.calculate_portions @order %>
36
+ <div class="col-sm-10">
37
+ <% portions.each do |item| %>
38
+ <%
39
+ total = Spree::Money.new(item[:total], {currency: @order.currency}).to_html
40
+ value = Spree::Money.new(item[:value], {currency: @order.currency}).to_html
41
+ %>
42
+ <%= radio_button_tag 'order[payments_attributes][][portions]', item[:portion], item[:portion] == 1 %>
43
+ <%= Spree.t(:komerci_portions, times: item[:portion], value: value,
44
+ tax: Spree.t(item[:tax_message]), total: total) %><br />
45
+ <% end %>
46
+ </div>
47
+ <div class="col-sm-2" id="komerci_cc_type"></div>
48
+ </div>
49
+
50
+ <%= hidden_field_tag "#{param_prefix}[cc_type]", '', id: 'cc_type' %>
51
+ </div>
52
+
53
+ <script type="text/javascript">
54
+ available_cc = {
55
+ visa: '<%= asset_url 'rede-credit-cards/rede-visa.png' %>',
56
+ mastercard: '<%= asset_url 'rede-credit-cards/rede-mastercard.png' %>',
57
+ dinersclub: '<%= asset_url 'rede-credit-cards/rede-dinersclub.png' %>',
58
+ hipercard: '<%= asset_url 'rede-credit-cards/rede-hipercard.png' %>',
59
+ jcb: '<%= asset_url 'rede-credit-cards/rede-jcb.png' %>'
60
+ };
61
+ new window.KomerciCreditCard(available_cc);
62
+ </script>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_zaez_komerci/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,31 @@
1
+ en:
2
+ spree:
3
+ komerci_settings: Komerci Settings
4
+ settings: Settings
5
+ affiltion_key: Affilition Key
6
+ komerci_user: Komerci User
7
+ komerci_password: Password of Komerci User
8
+ test_mode: Enable Test Mode
9
+ minimum_value: Minimum Value
10
+ portion_without_tax: Portions Without Tax
11
+ max_portion: Quantity of Portions Supported
12
+ tax_value: Tax Value
13
+ portions_type: Portions Type
14
+ portions_type_06: Portions by Issuing
15
+ portions_type_08: Portions by Store
16
+ komerci_without_tax: without tax.
17
+ komerci_with_tax: with tax.
18
+ komerci_adjustment_tax: Credit Card Tax
19
+ komerci_portions: "%{times}x of %{value} %{tax} (total: %{total})"
20
+ komerci:
21
+ messages:
22
+ purchase_success: "Komerci: transaction purchased successfully"
23
+ authorize_success: "Komerci: transaction authorized successfully"
24
+ capture_success: "Komerci: captured successfully"
25
+ void_success: "Komerci: Voided successfully"
26
+ cancel_success: "Komerci: Canceled successfully"
27
+ invalid_portions: "Komerci: The number of portions is required"
28
+ activerecord:
29
+ attributes:
30
+ spree/payment:
31
+ portions: Portions
@@ -0,0 +1,32 @@
1
+ pt-BR:
2
+ spree:
3
+ komerci_settings: Configurações Komerci
4
+ settings: Configuraçcões
5
+ affiltion_key: Número de Filiação
6
+ komerci_user: Usuário Komerci
7
+ komerci_password: Senha
8
+ test_mode: Habilitar ambiente de teste
9
+ minimum_value: Valor mínimo da parcela
10
+ portion_without_tax: Parcelas sem juros
11
+ max_portion: Quantidade máxima de parcelas
12
+ tax_value: Valor do juros
13
+ portions_type: Tipo de parcelamento
14
+ portions_type_06: Parcelado pelo emissor
15
+ portions_type_08: Parcelado pelo estabelecimento
16
+ komerci_without_tax: sem juros.
17
+ komerci_with_tax: com juros.
18
+ komerci_adjustment_tax: Juros do Cartão de Crédito
19
+ komerci_portions: "%{times}x de %{value} %{tax} (total: %{total})"
20
+ komerci:
21
+ messages:
22
+ purchase_success: "Komerci: transação processada com sucesso"
23
+ authorize_success: "Komerci: transação autorizada com sucesso"
24
+ capture_success: "Komerci: Capturado com sucesso"
25
+ void_success: "Komerci: Estornado com sucesso"
26
+ cancel_success: "Komerci: Cancelado com sucesso"
27
+ cancel_error_date: "Komerci: O cancelamento deve ser realizado no Portal pois o período para cancelar pelo e-commerce se encerrou."
28
+ invalid_portions: "Komerci: O número de parcelas é requerido"
29
+ activerecord:
30
+ attributes:
31
+ spree/payment:
32
+ portions: Parcelas
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ namespace :admin do
3
+ resource :komerci_settings, only: [:show, :edit, :update]
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddPortionsToSpreePayments < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_payments, :portions, :integer
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ class CreateSpreeKomerciTransaction < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_komerci_transactions do |t|
4
+ t.string :authorization_number
5
+ t.string :order_number
6
+ t.string :authentication_number
7
+ t.string :sequencial_number
8
+ t.string :bin
9
+ t.belongs_to :credit_card
10
+
11
+ t.timestamps null: false
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class AddPaymentIdToSpreeKomerciTransactions < ActiveRecord::Migration
2
+ def change
3
+ add_reference :spree_komerci_transactions, :payment, index: true, foreign_key: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddTotalToSpreeKomerciTransactions < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_komerci_transactions, :total, :decimal
4
+ end
5
+ end
@@ -0,0 +1,30 @@
1
+ module SpreeZaezKomerci
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, :type => :boolean, :default => false
6
+
7
+ def add_javascripts
8
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_zaez_komerci\n"
9
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_zaez_komerci\n"
10
+ end
11
+
12
+ def add_stylesheets
13
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_zaez_komerci\n", :before => /\*\//, :verbose => true
14
+ end
15
+
16
+ def add_migrations
17
+ run 'bundle exec rake railties:install:migrations FROM=spree_zaez_komerci'
18
+ end
19
+
20
+ def run_migrations
21
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
22
+ if run_migrations
23
+ run 'bundle exec rake db:migrate'
24
+ else
25
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,190 @@
1
+ class Spree::KomerciConfiguration < Spree::Preferences::Configuration
2
+
3
+ preference :afiliation_key, :string, default: '' # afiliation key
4
+ preference :komerci_user, :string, default: '' # Komerci user
5
+ preference :komerci_password, :string, default: '' # Password of Komerci user
6
+ preference :test_mode, :boolean, default: false # enable test mode
7
+ preference :minimum_value, :float, default: 5.0 # minimum value per portion (minimum is 5.00)
8
+ preference :tax_value, :float, default: 0.0 # tax value per month
9
+ preference :max_portion, :integer, default: 10 # quantity of portions supported
10
+ preference :portion_without_tax, :integer, default: 1 # number of portions without tax
11
+ preference :portions_type, :string, default: '06' # (04 = a vista, 06 = parcelado emissor, 08 = parcelado estabelecimento )
12
+
13
+ def authorize_uri
14
+ if preferred_test_mode
15
+ 'https://ecommerce.userede.com.br/pos_virtual/wskomerci/cap_teste.asmx/GetAuthorizedTst'
16
+ else
17
+ 'https://ecommerce.redecard.com.br/pos_virtual/wskomerci/cap.asmx/GetAuthorized'
18
+ end
19
+ end
20
+
21
+ def conf_authorization_uri
22
+ if preferred_test_mode
23
+ 'https://ecommerce.userede.com.br/pos_virtual/wskomerci/cap_teste.asmx/ConfPreAuthorizationTst'
24
+ else
25
+ 'https://ecommerce.redecard.com.br/pos_virtual/wskomerci/cap.asmx/ConfPreAuthorization'
26
+ end
27
+ end
28
+
29
+ def void_transaction_uri
30
+ if preferred_test_mode
31
+ 'https://ecommerce.userede.com.br/pos_virtual/wskomerci/cap_teste.asmx/VoidTransactionTst'
32
+ else
33
+ 'https://ecommerce.redecard.com.br/pos_virtual/wskomerci/cap.asmx/VoidTransaction'
34
+ end
35
+ end
36
+
37
+ def authorize(params)
38
+ response_xml = HTTParty.post(authorize_uri, body: params)
39
+ response = Hash.from_xml response_xml.body.gsub("\r\n ", '')
40
+ response = format_keys(response)
41
+ authorization = response[:authorization]
42
+
43
+ if authorization[:codret] == '0' and authorization[:numcv]
44
+ return {
45
+ success: true,
46
+ data: {
47
+ authorization_number: authorization[:numautor],
48
+ order_number: authorization[:numcv],
49
+ authentication_number: authorization[:numautent],
50
+ sequencial_number: authorization[:numsqn],
51
+ bin: authorization[:origem_bin]
52
+ }
53
+ }
54
+ else
55
+ return {
56
+ success: false,
57
+ data: {
58
+ error_number: authorization[:codret],
59
+ error_message: authorization[:msgret]
60
+ }
61
+ }
62
+ end
63
+ rescue REXML::ParseException
64
+ {
65
+ success: false,
66
+ data: {
67
+ error_message: response_xml.body.gsub("\r\n", '')
68
+ }
69
+ }
70
+ end
71
+
72
+ def conf_authorize(params)
73
+ response_xml = HTTParty.post(conf_authorization_uri, body: params)
74
+ response = Hash.from_xml response_xml.body.gsub("\r\n ", '')
75
+ response = format_keys(response)
76
+ confirmation = response[:confirmation][:root]
77
+
78
+ if confirmation[:codret] == '0'
79
+ return { success: true }
80
+ else
81
+ return {
82
+ success: false,
83
+ data: {
84
+ error_number: confirmation[:codret],
85
+ error_message: confirmation[:msgret]
86
+ }
87
+ }
88
+ end
89
+ rescue REXML::ParseException
90
+ {
91
+ success: false,
92
+ data: {
93
+ error_message: response_xml.body.gsub("\r\n", '')
94
+ }
95
+ }
96
+ end
97
+
98
+ def void_transaction params
99
+ response_xml = HTTParty.post(void_transaction_uri, body: params)
100
+ response = Hash.from_xml response_xml.body.gsub("\r\n ", '')
101
+ response = format_keys response
102
+ confirmation = response[:confirmation][:root]
103
+
104
+ if confirmation[:codret] == '0'
105
+ return { success: true }
106
+ else
107
+ return {
108
+ success: false,
109
+ data: {
110
+ error_number: confirmation[:codret],
111
+ error_message: confirmation[:msgret]
112
+ }
113
+ }
114
+ end
115
+ rescue REXML::ParseException
116
+ {
117
+ success: false,
118
+ data: {
119
+ error_message: response_xml.body.gsub("\r\n", '')
120
+ }
121
+ }
122
+ end
123
+
124
+ # Calculates the portions of credit card type
125
+ # based on Komerci configuration
126
+ #
127
+ # @param order [Spree::Order]
128
+ #
129
+ # @return [Array]
130
+ #
131
+ def calculate_portions(order)
132
+ amount = order.total.to_f
133
+ ret = []
134
+
135
+ portions_number = preferred_max_portion
136
+ minimum_value = preferred_minimum_value.to_f
137
+ tax = preferred_tax_value.to_f
138
+
139
+ ret.push({portion: 1, value: amount, total: amount, tax_message: :komerci_without_tax})
140
+
141
+ (2..portions_number).each do |number|
142
+ if tax <= 0 or number <= preferred_portion_without_tax
143
+ value = amount / number
144
+ tax_message = :komerci_without_tax
145
+ else
146
+ value = (amount * ((1 + tax / 100) ** number)) / number
147
+ tax_message = :komerci_with_tax
148
+ end
149
+
150
+ if value >= minimum_value
151
+ value_total = value * number
152
+ ret.push({portion: number, value: value, total: value_total, tax_message: tax_message})
153
+ end
154
+ end
155
+
156
+ ret
157
+ end
158
+
159
+ # Calculate the value of the portion based on Komerci configuration
160
+ # (verify if the portion has tax)
161
+ #
162
+ # @param order [Spree::Order]
163
+ # @param portion [Integer]
164
+ #
165
+ # @return [Float]
166
+ #
167
+ def calculate_portion_value(order, portion)
168
+ amount = order.total.to_f
169
+ amount = amount / 100 if amount.is_a? Integer
170
+ tax = preferred_tax_value.to_f
171
+
172
+ if tax <= 0 or portion <= preferred_portion_without_tax
173
+ value = amount / portion
174
+ else
175
+ value = (amount * ((1 + tax / 100) ** portion)) / portion
176
+ end
177
+ value
178
+ end
179
+
180
+ private
181
+
182
+ def format_keys hash
183
+ hash.inject({}) { |result, (key, value)|
184
+ value = format_keys(value) if value.is_a?(Hash)
185
+ result[(key.downcase.to_sym rescue key) || key] = value
186
+ result
187
+ }
188
+ end
189
+
190
+ end
@@ -0,0 +1,30 @@
1
+ module SpreeZaezKomerci
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_zaez_komerci'
6
+
7
+ # use rspec for tests
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+
12
+ initializer 'spree.zaez_komerci.preferences', after: :load_config_initializers do |app|
13
+ # require file with the preferences of the Billet
14
+ require 'spree/komerci_configuration'
15
+ Spree::KomerciConfig = Spree::KomerciConfiguration.new
16
+ end
17
+
18
+ initializer 'spree.zaez_komerci.payment_methods', after: 'spree.register.payment_methods' do |app|
19
+ app.config.spree.payment_methods << Spree::PaymentMethod::Komerci
20
+ end
21
+
22
+ def self.activate
23
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
24
+ Rails.configuration.cache_classes ? require(c) : load(c)
25
+ end
26
+ end
27
+
28
+ config.to_prepare &method(:activate).to_proc
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ FactoryGirl.define do
2
+ factory :komerci_payment_method, class: Spree::PaymentMethod::Komerci do
3
+ name 'Komerci'
4
+ created_at Date.today
5
+ end
6
+
7
+ factory :komerci_payment, class: Spree::Payment do
8
+ amount 15.00
9
+ order
10
+ state 'checkout'
11
+ portions 2
12
+ association(:payment_method, factory: :komerci_payment_method)
13
+ association(:source, factory: :credit_card_komerci)
14
+ end
15
+
16
+ factory :credit_card_komerci, class: Spree::CreditCard do
17
+ verification_value 123
18
+ month 12
19
+ year { 1.year.from_now.year }
20
+ number '4111111111111111'
21
+ name 'Spree Commerce'
22
+ cc_type 'visa'
23
+ association(:payment_method, factory: :komerci_payment_method)
24
+ end
25
+
26
+ factory :komerci_transaction, class: Spree::KomerciTransaction do
27
+ association(:credit_card, factory: :credit_card_komerci)
28
+ association(:payment, factory: :komerci_payment)
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ require 'spree_core'
2
+ require 'spree_zaez_komerci/engine'
3
+ require 'httparty'
4
+
5
+ Spree::PermittedAttributes.payment_attributes.push :portions
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Admin Komerci Payment', { type: :feature, js: true } do
4
+
5
+ let(:payment) { create(:komerci_payment, response_code: 'ABC1234') }
6
+ let!(:komerci_transaction) { create(:komerci_transaction, order_number: 'ABC1234', payment: payment) }
7
+
8
+ before(:all) { Spree::KomerciConfig[:test_mode] = true }
9
+ before { create_admin_and_sign_in }
10
+
11
+ context 'executing the actions' do
12
+
13
+ context 'capture the payment' do
14
+
15
+ let(:request_url) { Spree::KomerciConfig.conf_authorization_uri }
16
+
17
+ it 'should capture the payment' do
18
+ stub_request(:post, request_url).
19
+ with(body: hash_including({ 'filiacao' => Spree::KomerciConfig[:afiliation_key] })).
20
+ to_return(:body => File.read('spec/fixtures/conf_authorize_success.txt'), :status => 200)
21
+
22
+ visit spree.admin_order_payments_path payment.order
23
+ find('.action-capture').click
24
+
25
+ expect(page).to have_text 'Payment Updated'
26
+ within_row(1) do
27
+ expect(column_text(6)).to eq 'completed'
28
+ end
29
+ end
30
+
31
+ it 'should show an error message when try capture and fail' do
32
+ stub_request(:post, request_url).
33
+ with(body: hash_including({ 'filiacao' => Spree::KomerciConfig[:afiliation_key] })).
34
+ to_return(:body => File.read('spec/fixtures/conf_authorize_error.txt'), :status => 200)
35
+
36
+ visit spree.admin_order_payments_path payment.order
37
+ find('.action-capture').click
38
+
39
+ expect(page).to have_text '98: Cartão inválido'
40
+ within_row(1) do
41
+ expect(column_text(6)).to eq 'failed'
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'void the payment' do
47
+
48
+ let(:request_url) { Spree::KomerciConfig.void_transaction_uri }
49
+
50
+ it 'should void the payment' do
51
+ stub_request(:post, request_url).
52
+ with(body: hash_including({ 'filiacao' => Spree::KomerciConfig[:afiliation_key] })).
53
+ to_return(:body => File.read('spec/fixtures/void_success.txt'), :status => 200)
54
+
55
+ visit spree.admin_order_payments_path payment.order
56
+ find('.action-void').click
57
+
58
+ expect(page).to have_text 'Payment Updated'
59
+ within_row(1) do
60
+ expect(column_text(6)).to eq 'void'
61
+ end
62
+ end
63
+
64
+ it 'should show an error message when try void and fail' do
65
+ stub_request(:post, request_url).
66
+ with(body: hash_including({ 'filiacao' => Spree::KomerciConfig[:afiliation_key] })).
67
+ to_return(:body => File.read('spec/fixtures/void_error.txt'), :status => 200)
68
+
69
+ visit spree.admin_order_payments_path payment.order
70
+ find('.action-void').click
71
+
72
+ expect(page).to have_text '97: Data de estorno expirou'
73
+ within_row(1) do
74
+ expect(column_text(6)).to eq 'checkout'
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+ end