Skip to content

Commit

Permalink
Added verified purchaser
Browse files Browse the repository at this point in the history
One feature that many other eCommerce sites have is the concept of
a "verified purchaser" which is when someone leaves a review for a
product they verifiably purchased. In the implementation here we
add a toggle on whether to display the verfied purchaser on the
frontend, a column on the database to store if the review is from
a verified purchaser, and logic when creating the review to set
that value.
  • Loading branch information
ericsaupe committed Jun 13, 2019
1 parent 7c28054 commit d0e6253
Show file tree
Hide file tree
Showing 27 changed files with 123 additions and 7 deletions.
9 changes: 9 additions & 0 deletions app/helpers/spree/reviews_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ def txt_stars(n, show_out_of = true)
res
end

def display_verified_purchaser?(review)
Spree::Reviews::Config[:show_verified_purchaser] && review.user &&
Spree::LineItem.joins(:order, :variant)
.where.not(spree_orders: { completed_at: nil })
.find_by(
spree_variants: { product_id: review.product_id },
spree_orders: { user_id: review.user_id }
).present?
end
end
18 changes: 16 additions & 2 deletions app/models/spree/review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ class Spree::Review < ActiveRecord::Base
belongs_to :user, :class_name => Spree.user_class.to_s
has_many :feedback_reviews

before_create :verify_purchaser
after_save :recalculate_product_rating, :if => :approved?
after_destroy :recalculate_product_rating

validates :name, presence: true
validates :review, presence: true

validates :rating, numericality: { only_integer: true,
greater_than_or_equal_to: 1,
greater_than_or_equal_to: 1,
less_than_or_equal_to: 5,
message: :you_must_enter_value_for_rating }


default_scope { order("spree_reviews.created_at DESC") }

scope :localized, ->(lc) { where('spree_reviews.locale = ?', lc) }
scope :most_recent_first, -> { order('spree_reviews.created_at DESC') }
scope :oldest_first, -> { reorder('spree_reviews.created_at ASC') }
Expand All @@ -37,4 +38,17 @@ def recalculate_product_rating
def email
user.try!(:email)
end

def verify_purchaser
return unless user_id && product_id

verified_purchase = Spree::LineItem.joins(:order, :variant)
.where.not(spree_orders: { completed_at: nil })
.find_by(
spree_variants: { product_id: product_id },
spree_orders: { user_id: user_id }
).present?

self.verified_purchaser = verified_purchase
end
end
3 changes: 3 additions & 0 deletions app/models/spree/reviews_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def self.boolean_preferences
# show a reviewer's email address
preference :show_email, :boolean, :default => false

# show if a reviewer actually purchased the product
preference :show_verified_purchaser, :boolean, :default => false

# show helpfullness rating form elements
preference :feedback_rating, :boolean, :default => false

Expand Down
6 changes: 6 additions & 0 deletions app/views/spree/admin/review_settings/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
<%= I18n.t("spree.spree_reviews.show_email") %>
</label>
</div>
<div class="field">
<label>
<%= check_box_tag('preferences[show_verified_purchaser]', "1", Spree::Reviews::Config[:show_verified_purchaser]) %>
<%= I18n.t("spree.spree_reviews.show_verified_purchaser") %>
</label>
</div>
<div class="field">
<label>
<%= check_box_tag('preferences[require_login]', "1", Spree::Reviews::Config[:require_login]) %>
Expand Down
11 changes: 7 additions & 4 deletions app/views/spree/admin/reviews/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
<thead>
<tr>
<th><%= I18n.t("spree.product") %></th>
<th><%= Spree::Review.human_attribute_name(:rating) %></th>
<th><%= I18n.t("spree.feedback") %></th>
<th><%= "#{Spree::Review.human_attribute_name(:rating)}/#{I18n.t("spree.feedback")}" %></th>
<th><%= I18n.t("spree.verified_purchaser") %></th>
<th><%= Spree::Review.human_attribute_name(:user) %></th>
<th><%= Spree::Review.human_attribute_name(:created_at) %></th>
<th class="actions"></th>
Expand All @@ -83,10 +83,13 @@
<% end %>
</td>
<td class="align-center">
<%= txt_stars(review.rating) %>
<%= txt_stars(review.rating) %><br />
<%= link_to "(#{review.feedback_stars}/#{review.feedback_reviews.size})", admin_review_feedback_reviews_path(review) %>
</td>
<td class="align-center">
<%= link_to "(#{review.feedback_stars}/#{review.feedback_reviews.size})", admin_review_feedback_reviews_path(review) %>
<% if review.verified_purchaser? %>
<%= solidus_icon('fa fa-check') %>
<% end %>
</td>
<td class="align-center">
<%= review.user_id ? link_to(review.user.try(:email), [:admin, review.user]) : I18n.t("spree.anonymous") %></p>
Expand Down
3 changes: 3 additions & 0 deletions app/views/spree/shared/_review.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<% else %>
<span itemprop="author"><%= I18n.t("spree.anonymous") %></span>
<% end %>
<% if Spree::Reviews::Config[:show_verified_purchaser] && review.verified_purchaser? %>
<div><%= I18n.t("spree.verified_purchaser") %></div>
<% end %>
<div itemprop="reviewBody">
<%= simple_format(review.review) %>
</div>
Expand Down
2 changes: 2 additions & 0 deletions config/locales/de-CH.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ de-CH:
require_login: Login erforderlich
review_settings: Rezensionseinstellungen
show_email: E-Mail Adressen anzeigen
show_verified_purchaser: Verifizierten Käufer anzeigen
track_locale: Sprache des Benutzers tracken
star:
one: "ein Sternchen"
Expand All @@ -70,6 +71,7 @@ de-CH:
submit_your_review: Rezension abschicken
submitted_on: Eingeschickt am
unapproved_reviews: Nicht freigeschaltete Rezensionen
verified_purchaser: Verifizierter Käufer
voice:
one: "Eine Stimme"
other: "%{count} Stimmen"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ de:
require_login: Login erforderlich
review_settings: Rezensionseinstellungen
show_email: E-Mail Adressen anzeigen
show_verified_purchaser: Verifizierten Käufer anzeigen
track_locale: Sprache des Benutzers tracken
star:
one: "ein Sternchen"
Expand All @@ -70,6 +71,7 @@ de:
submit_your_review: Rezension abschicken
submitted_on: Eingeschickt am
unapproved_reviews: Nicht freigeschaltete Rezensionen
verified_purchaser: Verifizierter Käufer
voice:
one: "Eine Stimme"
other: "%{count} Stimmen"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en-GB.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ en-GB:
require_login: Require user to be logged in
review_settings: Review Settings
show_email: Show email addresses
show_verified_purchaser: Show verified purchaser
track_locale: Track user's locale
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ en-GB:
submit_your_review: Submit your review
submitted_on: Submitted on
unapproved_reviews: Unapproved
verified_purchaser: Verified purchaser
voice:
one: "1 voice"
other: "%{count} voices"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ en:
require_login: Require user to be logged in
review_settings: Review Settings
show_email: Show email addresses
show_verified_purchaser: Show verified purchaser
track_locale: Track user's locale
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ en:
submit_your_review: Submit your review
submitted_on: Submitted on
unapproved_reviews: Unapproved
verified_purchaser: Verified purchaser
voice:
one: "1 voice"
other: "%{count} voices"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ es:
require_login: "Requerir que el usuario esté logado"
review_settings: "Configuración de las Valoraciones"
show_email: "Mostrar las direcciones de correo"
show_verified_purchaser: Mostrar comprador verificado
track_locale: "Rastrear el locale del usuario"
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ es:
submit_your_review: "Envía tu valoración"
submitted_on: "Enviada el"
unapproved_reviews: "Sin aprobar"
verified_purchaser: Comprador verificado
voice:
one: "1 voz"
other: "%{count} voces"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fr:
require_login: Demander à l'utilisateur d'être connecté
review_settings: Paramètres des commentaires
show_email: Montrer l'adresse de courriel
show_verified_purchaser: Montrer l'acheteur vérifié
track_locale: Détécter la langue de l'utilisateur
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ fr:
submit_your_review: Envoyer votre commentaire
submitted_on: Envoyé le
unapproved_reviews: Non approuvé
verified_purchaser: Acheteur vérifié
voice:
one: "1 voix"
other: "%{count} voix"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ it:
require_login: "L'utente deve essere loggato"
review_settings: Impostazioni recensioni
show_email: "Mostra l'indirizzo email"
show_verified_purchaser: Mostra acquirente verificato
track_locale: "Mostra solo le recensioni con lo stesso locale dell'utente"
star:
one: "1"
Expand All @@ -68,6 +69,7 @@ it:
submit_your_review: Salva la recensione
submitted_on: Salvata su
unapproved_reviews: Non approvate
verified_purchaser: Acquirente verificato
voice:
one: "1 voto"
other: "%{count} voti"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/pl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pl:
require_login: "Wymagaj, aby użytkownik był zalogowany"
review_settings: Ustawienia opinii
show_email: Pokaż adresy email
show_verified_purchaser: Pokaż zweryfikowanego nabywcę
track_locale: Śledź język użytkownika
star:
one: "1"
Expand All @@ -72,6 +73,7 @@ pl:
submit_your_review: Dodaj opinię
submitted_on: Dodano
unapproved_reviews: Niezaakceptowane
verified_purchaser: Zweryfikowany nabywca
voice:
one: "1 głos"
few: "%{count} głosów"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pt-BR:
require_login: 'É necessário estar logado'
review_settings: 'Configurações de avaliação'
show_email: 'Mostrar endereço de email'
show_verified_purchaser: Mostrar comprador confirmado
track_locale: 'Rastrear localização do usuário'
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ pt-BR:
submit_your_review: 'Enviar sua avaliação'
submitted_on: 'Enviado em'
unapproved_reviews: 'Desaprovado'
verified_purchaser: Comprador verificado
voice:
one: "1 voz"
other: "%{count} vozes"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/pt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pt:
require_login: Requerer que utilizador esteja registado
review_settings: Configurações de Avaliação
show_email: Mostrar email
show_verified_purchaser: Mostrar comprador confirmado
track_locale: Seguir locale do utilizador
star:
one: "1"
Expand All @@ -70,6 +71,7 @@ pt:
submit_your_review: Envia tua avaliação
submitted_on: Enviada em
unapproved_reviews: Não aprovadas
verified_purchaser: Comprador verificado
voice:
one: "uma opinião"
other: "%{count} opiniões"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/ro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ ro:
require_login: Solicită ca utilizatorul să fie autentificat
review_settings: Setări recenzii
show_email: Afișează adresa de email
show_verified_purchaser: Afișați cumpărătorul verificat
track_locale: Urmărește setarea de limbă a utilizatorului
star:
one: "o stea"
Expand All @@ -75,6 +76,7 @@ ro:
submit_your_review: Trimite recenzia
submitted_on: Trimisă la
unapproved_reviews: Neaprobat
verified_purchaser: Achizitor verificat
voice:
one: "o opinie"
few: "%{count} opinii"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ ru:
your_location: Город
feedback_rating: Рейтинг отзыва
show_email: Показывать электронную почту
show_verified_purchaser: Показать подтвержденного покупателя
require_login: Требовать вход
track_locale: Отслеживать язык
average_customer_rating: Средняя оценка
Expand All @@ -63,6 +64,7 @@ ru:
by: ""
submitted_on: Добавлено
based_upon: "на основе"
verified_purchaser: Проверенный покупатель
voice:
zero: "0 голосов"
one: "%{count} голос"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/sv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ sv:
require_login: "Kräv att användaren är inloggad"
review_settings: "Recensions inställningar"
show_email: "Visa epost adresser"
show_verified_purchaser: Visa verifierad köpare
track_locale: "Spåra användarens språk"
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ sv:
submit_your_review: "Skicka in din recension"
submitted_on: "Skapad den"
unapproved_reviews: "Icke godkänd"
verified_purchaser: Verifierad köpare
voice:
one: "1 röst"
other: "%{count} röster"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/tr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ tr:
require_login: Yorumları görebilmek için kullanıcı girişi
review_settings: Yorum Ayarları
show_email: e-posta adresini göster
show_verified_purchaser: Doğrulanmış alıcıyı göster
track_locale: Kullanıcının yerel bilgilerini kaydet/takip et
star:
one: "1"
Expand All @@ -69,6 +70,7 @@ tr:
submit_your_review: Gönder
submitted_on: "Gönderilme Tarihi:"
unapproved_reviews: Onaylanmamış
verified_purchaser: Doğrulanmış alıcı
voice:
one: "1 değerlendirme"
other: "%{count} değerlendirme"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/uk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ uk:
require_login: Тільки для зареєстрованих користувачів
review_settings: Налаштування відгуків
show_email: Показувати email
show_verified_purchaser: Показати підтвердженого покупця
track_locale: Зберігати мову користувача
star:
one: '1'
Expand All @@ -75,6 +76,7 @@ uk:
submit_your_review: Надіслати відгук
submitted_on: Написано
unapproved_reviews: Непідтверджений
verified_purchaser: Перевірений покупець
voice:
one: '1 голос'
few: '%{count} голоси'
Expand Down
2 changes: 2 additions & 0 deletions config/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ zh-CN:
require_login: 用者必需登入
review_settings: 评论设定
show_email: 显示电邮地址
show_verified_purchaser: 显示经过验证的购买者
track_locale: 追踪用户地域
star:
one: "1"
Expand All @@ -67,6 +68,7 @@ zh-CN:
submit_your_review: 递交你的评论
submitted_on: 递交日期
unapproved_reviews: 沒核准
verified_purchaser: 验证购买者
voice:
one: "1 聲音"
other: "%{count} 聲音"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/zh-TW.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ zh-TW:
require_login: 用者必需登入
review_settings: 評論設定
show_email: 顯示電郵地址
show_verified_purchaser: 顯示經過驗證的購買者
track_locale: 追蹤用戶地域
star:
one: "1"
Expand All @@ -67,6 +68,7 @@ zh-TW:
submit_your_review: 遞交你的評論
submitted_on: 遞交日期
unapproved_reviews: 沒核準
verified_purchaser: 驗證購買者
voice:
one: "1 聲音"
other: "%{count} 聲音"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddVerifiedPurchaserToReviews < SolidusSupport::Migration[4.2]
def change
add_column :spree_reviews, :verified_purchaser, :boolean, default: false
end
end
Loading

0 comments on commit d0e6253

Please sign in to comment.