Solidus Brazilian Adaptations
Essa gem tem como objetivo adaptar os modelos do Solidus para se adequar aos padrões brasileiros, tais como a criação dos atributos CPF/CNPJ (tax_id) em Spree::Order, e número (number) do imóvel e bairro (district) em Spree::Address.
Installation
Add solidus_brazilian_adaptations to your Gemfile:
gem 'solidus_brazilian_adaptations'
Bundle your dependencies and run the installation generator:
bin/rails generate solidus_brazilian_adaptations:install
Usage
Tradução e moeda padrão
Editar config/initializers/spree.rb
adicionando as seguintes configurações:
Mudar moeda e país padrão:
Spree.config do |config|
config.currency = "BRL"
config.default_country_iso = "BR"
end
Mudar idioma da interface do admin:
Spree::Backend::Config.configure do |config|
config.locale = 'pt-BR'
end
Incluir no config/application.rb
para definir os locales disponiveis:
module SuaLoja
class Application < Rails::Application
config.i18n.available_locales = ['pt-BR']
config.i18n.default_locale = 'pt-BR'
end
end
Seeds
Substituir Spree::Core::Engine.load_seed
por SolidusBrazilianAdaptations::Engine.load_seed
em db/seeds.rb
para utilizar o seeds da gem.
Configurações
A partir do initializer da gem é possivel configurar se será permitido efetuar compras utilizando CNPJ. Por padrão é essa opção é true
.
Storefront
Essa gem utiliza o starter frontend como base, então os exemplos serão feitos a partir de suas views.
Para adicionar os campos de CPF/CNPJ, número e bairro é possivel editar o form da etapa de endereço. Porém a edição é feita em duas partials diferentes:
Na partial app/views/checkouts/_checkout_step.html.erb
o seguinte HTML referente ao CPF/CNPJ pode ser inserido logo abaixo ao input de e-mail:
<%= form_for order, url: update_checkout_path(order.state), html: { id: "checkout_form_#{order.state}" } do |form| %>
<% if order.state == "address" || !order.email? %>
<div class="text-input">
<%= form.label :email, 'E-Mail:' %>
<%= form.email_field :email, required: true, placeholder: 'name@example.com' %>
</div>
<!-- Adicionar -->
<% label = SolidusBrazilianAdaptations.config.allow_cnpj ? "CPF/CPNJ" : "CPF" %>
<div class="text-input" style="margin-top: 4px;">
<%= form.label :tax_id, "#{label}:" %>
<%= form.text_field :tax_id, required: true, placeholder: label %>
</div>
<!-- ********* -->
<% end %>
<%= render "checkouts/steps/#{order.state}_step", form: form, differentiator: @differentiator %>
<% end %>
E na partial app/views/checkouts/steps/address_step/_address_inputs.html.erb
adicionar o seguinte código referente ao número e bairro, podendo ser alterada a ordem dos campos:
<!-- Adicionar -->
<div class="text-input">
<%= form.label :number, "Número:" %>
<%= form.text_field :number, required: true %>
</div>
<!-- ********* -->
<div class="text-input">
<%= form.label :address2, "#{I18n.t("spree.street_address_2")}:" %>
<%= form.text_field :address2, autocomplete: "#{address_type} address-line2" %>
</div>
<!-- Adicionar -->
<div class="text-input">
<%= form.label :district, "Bairro:" %>
<%= form.text_field :district, required: true %>
</div>
<!-- ********* -->
<div class="text-input">
<%= form.label :city, "#{I18n.t("spree.city")}:" %>
<%= form.text_field :city, required: true, autocomplete: "#{address_type} address-level2" %>
</div>
Admin
Para visualizar os campos de CPF/CNPJ, número e bairro no painel do Admin na aba Order/Order_Number/Customer Details
é necessário criar as seguintes views em seu projeto:
Essas novas views irão sobrescrever as padrões, localizadas na gem solidus_backend
. Portanto, você deve ficar atento às atualizações do Solidus, pois ao sobrescrever as views as atualizações não serão aplicadas.
app/views/spree/admin/orders/customer_details/_form.html.erb
<fieldset data-hook="admin_customer_detail_form_fields" class="no-border-top">
<fieldset class="index no-border-bottom" data-hook="customer_guest">
<legend align="center"><%= t('spree.account') %></legend>
<div data-hook="customer_fields" class="row">
<div class="col-9">
<div class="field">
<%= f.label :email %>
<%= f.email_field :email, required: true, class: 'fullwidth' %>
</div>
<!-- Adicionado -->
<div class="field">
<%= f.label :tax_id, "CPF/CNPJ" %>
<%= f.text_field :tax_id, required: true, class: 'fullwidth' %>
</div>
<!-- ********* -->
</div>
<div class="col-3">
<div class="field">
<%= label_tag nil, t('spree.guest_checkout') %>
<ul>
<% if @order.completed? %>
<li>
<%= @order.user.nil? ? t('spree.say_yes') : t('spree.say_no') %>
</li>
<% else %>
<% guest = @order.user.nil? %>
<li>
<label>
<%= radio_button_tag :guest_checkout, true, guest %>
<%= t('spree.say_yes') %>
</label>
</li>
<li>
<label>
<%= radio_button_tag :guest_checkout, false, !guest, disabled: @order.cart? %>
<%= t('spree.say_no') %>
</label>
</li>
<%= hidden_field_tag :user_id, @order.user_id %>
<% end %>
</ul>
</div>
</div>
</div>
</fieldset>
<div class="row">
<% if Spree::Config[:order_bill_address_used] %>
<div class="col-6" data-hook="bill_address_wrapper">
<fieldset class="no-border-bottom">
<legend align="center"><%= t('spree.billing_address') %></legend>
<div class="js-billing-address">
<%= f.fields_for :bill_address do |ba_form| %>
<%= render partial: 'spree/admin/shared/address_form', locals: { f: ba_form, type: "billing" } %>
<% end %>
</div>
</fieldset>
</div>
<% end %>
<div class="col-6" data-hook="ship_address_wrapper">
<fieldset class="no-border-bottom">
<legend align="center"><%= t('spree.shipping_address') %></legend>
<% if Spree::Config[:order_bill_address_used] %>
<div class="field">
<span data-hook="use_billing">
<label>
<%= check_box_tag 'order[use_billing]', '1', (@order.ship_address.new_record? && @order.bill_address == @order.ship_address) %>
<%= t('spree.use_billing_address') %>
</label>
</span>
</div>
<% end %>
<div class="js-shipping-address">
<%= f.fields_for :ship_address do |ba_form| %>
<%= render partial: 'spree/admin/shared/address_form', locals: { f: ba_form, type: "shipping" } %>
<% end %>
</div>
</fieldset>
</div>
</div>
<div class="clear"></div>
<div class="form-buttons filter-actions actions" data-hook="buttons">
<%= button_tag t('spree.actions.update'), class: 'btn btn-primary' %>
</div>
</fieldset>
app/views/spree/admin/shared/_address_form.html.erb
<% s_or_b = type.chars.first %>
<div id="<%= type %>" data-hook="address_fields">
<div class="field <%= "#{type}-row" %>">
<%= f.label :name %>
<%= f.text_field :name, class: 'fullwidth' %>
</div>
<% if Spree::Config[:company] %>
<div class="field <%= "#{type}-row" %>">
<%= f.label :company %>
<%= f.text_field :company, class: 'fullwidth' %>
</div>
<% end %>
<div class="field <%= "#{type}-row" %>">
<%= f.label :address1 %>
<%= f.text_field :address1, class: 'fullwidth' %>
</div>
<!-- Adicionado -->
<div class="field <%= "#{type}-row" %>">
<%= f.label :number, "Número" %>
<%= f.text_field :number, class: 'fullwidth' %>
</div>
<!-- ********** -->
<div class="field <%= "#{type}-row" %>">
<%= f.label :address2 %>
<%= f.text_field :address2, class: 'fullwidth' %>
</div>
<!-- Adicionado -->
<div class="field <%= "#{type}-row" %>">
<%= f.label :district, "Bairro" %>
<%= f.text_field :district, class: 'fullwidth' %>
</div>
<!-- ********** -->
<div class="field <%= "#{type}-row" %>">
<%= f.label :city %>
<%= f.text_field :city, class: 'fullwidth' %>
</div>
<div class="field <%= "#{type}-row" %>">
<%= f.label :zipcode %>
<%= f.text_field :zipcode, class: 'fullwidth' %>
</div>
<div class="field <%= "#{type}-row" %>">
<%= f.label :country_id, Spree::Country.model_name.human %>
<span id="<%= s_or_b %>country">
<%= f.collection_select :country_id, available_countries, :id, :name, {}, {class: 'custom-select fullwidth js-country_id'} %>
</span>
</div>
<div class="field <%= "#{type}-row" %>">
<%= f.label :state_id, Spree::State.model_name.human %>
<span id="<%= s_or_b %>state">
<%= f.hidden_field :state_name, value: nil %>
<% states = f.object.country.try(:states).nil? ? [] : f.object.country.states %>
<%= f.text_field :state_name,
style: "display: #{states.empty? ? 'block' : 'none' };",
disabled: !states.empty?, class: 'fullwidth state_name js-state_name' %>
<%= f.hidden_field :state_id, value: nil %>
<%= f.collection_select :state_id,
states.sort,
:id, :name,
{ include_blank: true },
{ class: 'custom-select fullwidth js-state_id',
style: "display: #{states.empty? ? 'none' : 'block' };",
disabled: states.empty? } %>
</span>
</div>
<div class="field <%= "#{type}-row" %>">
<%= f.label :phone %>
<%= f.phone_field :phone, class: 'fullwidth' %>
</div>
</div>