workarea-reviews 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.eslintignore +2 -0
- data/.eslintrc +24 -0
- data/.eslintrc.json +35 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ci.yml +60 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +3 -0
- data/.scss-lint.yml +188 -0
- data/.stylelintrc.json +8 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +745 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +8 -0
- data/LICENSE +52 -0
- data/README.md +107 -0
- data/Rakefile +53 -0
- data/app/assets/images/workarea/admin/icons/star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/empty_star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/half_star.svg +1 -0
- data/app/assets/images/workarea/storefront/icons/star.svg +1 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/product_review_ajax_submit.js +39 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/product_reviews_sort_menus.js +82 -0
- data/app/assets/javascripts/workarea/storefront/reviews/modules/rating_buttons.js +103 -0
- data/app/assets/javascripts/workarea/storefront/reviews/templates/sort_by_property.jst.ejs +11 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_rating.scss +28 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews.scss +59 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_reviews_aggregate.scss +38 -0
- data/app/assets/stylesheets/workarea/storefront/reviews/components/_write_review.scss +63 -0
- data/app/controllers/workarea/admin/catalog_products_controller.decorator +9 -0
- data/app/controllers/workarea/admin/reports_controller.decorator +10 -0
- data/app/controllers/workarea/admin/reviews_controller.rb +51 -0
- data/app/controllers/workarea/storefront/review_requests_controller.rb +50 -0
- data/app/controllers/workarea/storefront/reviews_controller.rb +53 -0
- data/app/helpers/workarea/admin/reviews_helper.rb +13 -0
- data/app/helpers/workarea/storefront/reviews_helper.rb +22 -0
- data/app/helpers/workarea/storefront/reviews_schema_org_helper.rb +34 -0
- data/app/mailers/workarea/admin/status_report_mailer.decorator +8 -0
- data/app/mailers/workarea/storefront/review_mailer.rb +23 -0
- data/app/models/workarea/catalog/product.decorator +15 -0
- data/app/models/workarea/fulfillment.decorator +11 -0
- data/app/models/workarea/insights/most_active_reviewers.rb +34 -0
- data/app/models/workarea/insights/most_reviewed_products.rb +33 -0
- data/app/models/workarea/insights/top_rated_products.rb +33 -0
- data/app/models/workarea/review.rb +124 -0
- data/app/models/workarea/review/request.rb +62 -0
- data/app/models/workarea/search/admin/review.rb +72 -0
- data/app/models/workarea/search/storefront/product.decorator +9 -0
- data/app/models/workarea/sort.decorator +17 -0
- data/app/queries/workarea/reports/reviews_by_product.rb +86 -0
- data/app/queries/workarea/reports/reviews_by_user.rb +71 -0
- data/app/queries/workarea/review_request_params.rb +47 -0
- data/app/queries/workarea/review_summary.rb +11 -0
- data/app/queries/workarea/search/admin_reviews.rb +40 -0
- data/app/queries/workarea/search/category_browse.decorator +9 -0
- data/app/queries/workarea/search/product_search.decorator +9 -0
- data/app/seeds/workarea/review_seeds.rb +49 -0
- data/app/services/workarea/create_review.rb +99 -0
- data/app/view_models/workarea/admin/dashboards/reports_view_model.decorator +11 -0
- data/app/view_models/workarea/admin/product_view_model.decorator +7 -0
- data/app/view_models/workarea/admin/reports/reviews_by_product_view_model.rb +27 -0
- data/app/view_models/workarea/admin/review_view_model.rb +23 -0
- data/app/view_models/workarea/admin/reviews_search_view_model.rb +46 -0
- data/app/view_models/workarea/storefront/product_view_model.decorator +13 -0
- data/app/view_models/workarea/storefront/review_view_model.rb +14 -0
- data/app/views/workarea/admin/activities/_review_create.html.haml +12 -0
- data/app/views/workarea/admin/activities/_review_destroy.html.haml +10 -0
- data/app/views/workarea/admin/activities/_review_update.html.haml +10 -0
- data/app/views/workarea/admin/dashboards/_reviews_by_product_card.html.haml +17 -0
- data/app/views/workarea/admin/insights/_most_active_reviewers.html.haml +22 -0
- data/app/views/workarea/admin/insights/_most_reviewed_products.html.haml +22 -0
- data/app/views/workarea/admin/insights/_top_rated_products.html.haml +22 -0
- data/app/views/workarea/admin/reports/reviews_by_product.html.haml +44 -0
- data/app/views/workarea/admin/reviews/_aux_navigation.html.haml +5 -0
- data/app/views/workarea/admin/reviews/_catalog_products_aux_link.html.haml +5 -0
- data/app/views/workarea/admin/reviews/_dashboard_navigation.html.haml +1 -0
- data/app/views/workarea/admin/reviews/_menu.html.haml +3 -0
- data/app/views/workarea/admin/reviews/_summary.html.haml +12 -0
- data/app/views/workarea/admin/reviews/edit.html.haml +77 -0
- data/app/views/workarea/admin/reviews/index.html.haml +74 -0
- data/app/views/workarea/admin/status_report_mailer/_reviews.html.haml +5 -0
- data/app/views/workarea/storefront/products/_rating.html.haml +9 -0
- data/app/views/workarea/storefront/products/_reviews.html.haml +23 -0
- data/app/views/workarea/storefront/products/_reviews_aggregate.html.haml +22 -0
- data/app/views/workarea/storefront/products/_reviews_summary.html.haml +2 -0
- data/app/views/workarea/storefront/review_mailer/review_request.html.haml +24 -0
- data/app/views/workarea/storefront/review_requests/show.html.haml +45 -0
- data/app/views/workarea/storefront/reviews/new.html.haml +68 -0
- data/app/views/workarea/storefront/style_guides/_reviews_product_summary_docs.html.haml +13 -0
- data/app/views/workarea/storefront/style_guides/components/_reviews.html.haml +17 -0
- data/app/workers/workarea/create_review_requests.rb +33 -0
- data/app/workers/workarea/schedule_review_requests.rb +44 -0
- data/app/workers/workarea/send_review_requests.rb +12 -0
- data/app/workers/workarea/update_product_review_data.rb +26 -0
- data/bin/rails +18 -0
- data/config/initializers/append_points.rb +75 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/configuration.rb +31 -0
- data/config/initializers/rack_attack.rb +11 -0
- data/config/initializers/recaptcha.rb +19 -0
- data/config/initializers/scheduled_jobs.rb +8 -0
- data/config/locales/en.yml +150 -0
- data/config/routes.rb +25 -0
- data/lib/tasks/verify.rake +16 -0
- data/lib/workarea/mailer_previews/storefront/review_mailer_preview.rb +10 -0
- data/lib/workarea/reviews.rb +13 -0
- data/lib/workarea/reviews/engine.rb +16 -0
- data/lib/workarea/reviews/version.rb +5 -0
- data/package.json +9 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +25 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +55 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +43 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
- data/test/dummy/config/initializers/session_store.rb +5 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/factories/reviews.rb +32 -0
- data/test/fixtures/reviews.csv +5 -0
- data/test/helpers/workarea/storefront/reviews_helper_test.rb +20 -0
- data/test/integration/workarea/admin/reviews_integration_test.rb +37 -0
- data/test/integration/workarea/storefront/review_requests_integration_test.rb +63 -0
- data/test/integration/workarea/storefront/reviews_integration_test.rb +82 -0
- data/test/javascripts/fixtures/product_review_ajax_submit.html.haml +4 -0
- data/test/javascripts/product_review_ajax_submit_spec.js +28 -0
- data/test/javascripts/spec_helper.js +23 -0
- data/test/models/workarea/insights/most_active_reviewers_test.rb +32 -0
- data/test/models/workarea/insights/most_reviewed_products_test.rb +32 -0
- data/test/models/workarea/insights/top_rated_products_test.rb +49 -0
- data/test/models/workarea/review/request_test.rb +18 -0
- data/test/models/workarea/review_test.rb +105 -0
- data/test/models/workarea/search/storefront/product_test.decorator +14 -0
- data/test/queries/workarea/reports/reviews_by_product_test.rb +104 -0
- data/test/queries/workarea/reports/reviews_by_user_test.rb +102 -0
- data/test/queries/workarea/review_request_params_test.rb +64 -0
- data/test/services/workarea/create_review_test.rb +131 -0
- data/test/system/workarea/admin/review_system_test.rb +96 -0
- data/test/system/workarea/admin/reviews_by_product_system_test.rb +60 -0
- data/test/system/workarea/storefront/review_request_system_test.rb +34 -0
- data/test/system/workarea/storefront/review_system_test.rb +113 -0
- data/test/teaspoon_env.rb +10 -0
- data/test/test_helper.rb +11 -0
- data/test/workers/workarea/create_review_requests_test.rb +38 -0
- data/test/workers/workarea/schedule_review_requests_test.rb +115 -0
- data/test/workers/workarea/send_review_requests_test.rb +30 -0
- data/workarea-reviews.gemspec +22 -0
- data/yarn.lock +3265 -0
- metadata +265 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Reports
|
3
|
+
class ReviewsByProduct
|
4
|
+
include Report
|
5
|
+
|
6
|
+
self.reporting_class = Review
|
7
|
+
self.sort_fields = %w(reviews verified average_rating weighted_average_rating)
|
8
|
+
|
9
|
+
def aggregation
|
10
|
+
[filter_results, project_used_fields, group_by_product, project_averages]
|
11
|
+
end
|
12
|
+
|
13
|
+
def filter_results
|
14
|
+
{
|
15
|
+
'$match' => {
|
16
|
+
'created_at' => { '$gte' => starts_at, '$lte' => ends_at },
|
17
|
+
**approval_query
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def project_used_fields
|
23
|
+
{
|
24
|
+
'$project' => {
|
25
|
+
'product_id' => 1,
|
26
|
+
'rating' => 1,
|
27
|
+
'verified' => 1
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def group_by_product
|
33
|
+
{
|
34
|
+
'$group' => {
|
35
|
+
'_id' => '$product_id',
|
36
|
+
'reviews' => { '$sum' => 1 },
|
37
|
+
'verified' => { '$sum' => { '$cond' => { 'if' => '$verified', 'then' => 1, 'else' => 0 } } },
|
38
|
+
'rating_tally' => { '$sum' => '$rating' },
|
39
|
+
'rated_5' => { '$sum' => { '$cond' => { 'if' => { '$eq' => ['$rating', 5] }, 'then' => 1, 'else' => 0 } } },
|
40
|
+
'rated_4' => { '$sum' => { '$cond' => { 'if' => { '$eq' => ['$rating', 4] }, 'then' => 1, 'else' => 0 } } },
|
41
|
+
'rated_3' => { '$sum' => { '$cond' => { 'if' => { '$eq' => ['$rating', 3] }, 'then' => 1, 'else' => 0 } } },
|
42
|
+
'rated_2' => { '$sum' => { '$cond' => { 'if' => { '$eq' => ['$rating', 2] }, 'then' => 1, 'else' => 0 } } },
|
43
|
+
'rated_1' => { '$sum' => { '$cond' => { 'if' => { '$eq' => ['$rating', 1] }, 'then' => 1, 'else' => 0 } } }
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def project_averages
|
49
|
+
{
|
50
|
+
'$project' => {
|
51
|
+
'product_id' => 1,
|
52
|
+
'reviews' => 1,
|
53
|
+
'verified' => 1,
|
54
|
+
'average_rating' => { '$divide' => ['$rating_tally', '$reviews'] },
|
55
|
+
'weighted_average_rating' => {
|
56
|
+
'$divide' => [
|
57
|
+
{
|
58
|
+
'$sum' => [
|
59
|
+
{ '$multiply' => [{ '$sum' => [2, '$rated_5'] }, 5] },
|
60
|
+
{ '$multiply' => [{ '$sum' => [2, '$rated_4'] }, 4] },
|
61
|
+
{ '$multiply' => [{ '$sum' => [2, '$rated_3'] }, 3] },
|
62
|
+
{ '$multiply' => [{ '$sum' => [2, '$rated_2'] }, 2] },
|
63
|
+
{ '$multiply' => [{ '$sum' => [2, '$rated_1'] }, 1] }
|
64
|
+
]
|
65
|
+
},
|
66
|
+
{ '$sum' => [10, '$rated_5', '$rated_4', '$rated_3', '$rated_2', '$rated_1'] }
|
67
|
+
]
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def approval_query
|
76
|
+
if params[:results_filter] == 'approved'
|
77
|
+
{ approved: true }
|
78
|
+
elsif params[:results_filter] == 'unapproved'
|
79
|
+
{ approved: false }
|
80
|
+
else
|
81
|
+
{}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Reports
|
3
|
+
class ReviewsByUser
|
4
|
+
include Report
|
5
|
+
|
6
|
+
self.reporting_class = Review
|
7
|
+
self.sort_fields = %w(reviews verified average_rating activity_score)
|
8
|
+
|
9
|
+
def aggregation
|
10
|
+
[filter_results, project_used_fields, group_by_email, project_fields]
|
11
|
+
end
|
12
|
+
|
13
|
+
def filter_results
|
14
|
+
{
|
15
|
+
'$match' => {
|
16
|
+
'created_at' => { '$gte' => starts_at, '$lte' => ends_at },
|
17
|
+
**approval_query
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def project_used_fields
|
23
|
+
{
|
24
|
+
'$project' => {
|
25
|
+
'email' => 1,
|
26
|
+
'user_id' => 1,
|
27
|
+
'rating' => 1,
|
28
|
+
'verified' => 1
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def group_by_email
|
34
|
+
{
|
35
|
+
'$group' => {
|
36
|
+
'_id' => '$email',
|
37
|
+
'user_id' => { '$max' => '$user_id' },
|
38
|
+
'reviews' => { '$sum' => 1 },
|
39
|
+
'verified' => { '$sum' => { '$cond' => { 'if' => '$verified', 'then' => 1, 'else' => 0 } } },
|
40
|
+
'rating_tally' => { '$sum' => '$rating' }
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def project_fields
|
46
|
+
{
|
47
|
+
'$project' => {
|
48
|
+
'email' => 1,
|
49
|
+
'user_id' => 1,
|
50
|
+
'reviews' => 1,
|
51
|
+
'verified' => 1,
|
52
|
+
'average_rating' => { '$divide' => ['$rating_tally', '$reviews'] },
|
53
|
+
'activity_score' => { '$sum' => ['$reviews', { '$multiply' => ['$verified', 0.75] }] }
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def approval_query
|
61
|
+
if params[:results_filter] == 'approved'
|
62
|
+
{ approved: true }
|
63
|
+
elsif params[:results_filter] == 'unapproved'
|
64
|
+
{ approved: false }
|
65
|
+
else
|
66
|
+
{}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Workarea
|
2
|
+
class ReviewRequestParams
|
3
|
+
attr_reader :request, :params
|
4
|
+
|
5
|
+
def initialize(request, params)
|
6
|
+
@request = request
|
7
|
+
@params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_h
|
11
|
+
params.merge(
|
12
|
+
product_id: @request.product_id,
|
13
|
+
user_id: @request.user_id,
|
14
|
+
email: @request.email,
|
15
|
+
user_info: user_info,
|
16
|
+
first_name: first_name,
|
17
|
+
last_name: last_name,
|
18
|
+
verified: true
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def user_info
|
25
|
+
return user.public_info if user&.public_info.present?
|
26
|
+
|
27
|
+
[first_name.first, last_name.first].join
|
28
|
+
end
|
29
|
+
|
30
|
+
def first_name
|
31
|
+
user&.first_name || billing_address.first_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def last_name
|
35
|
+
user&.last_name || billing_address.last_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def user
|
39
|
+
return nil unless @request.user_id.present?
|
40
|
+
@user ||= User.find(@request.user_id)
|
41
|
+
end
|
42
|
+
|
43
|
+
def billing_address
|
44
|
+
@billing_address ||= Payment.find(@request.order_id).address
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Search
|
3
|
+
class AdminReviews
|
4
|
+
include Query
|
5
|
+
include AdminIndexSearch
|
6
|
+
include AdminSorting
|
7
|
+
include Pagination
|
8
|
+
|
9
|
+
document Search::Admin
|
10
|
+
|
11
|
+
def initialize(params = {})
|
12
|
+
super(params.merge(type: 'review'))
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields
|
16
|
+
super + %w(review_text)
|
17
|
+
end
|
18
|
+
|
19
|
+
def facets
|
20
|
+
super + [
|
21
|
+
TermsFacet.new(self, 'state'),
|
22
|
+
TermsFacet.new(self, 'rating'),
|
23
|
+
TermsFacet.new(self, 'verification')
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
def sort
|
28
|
+
result = super || []
|
29
|
+
|
30
|
+
if params[:sort] == Sort.highest_rating.to_s
|
31
|
+
result.prepend(Sort.highest_rating.field => Sort.highest_rating.direction)
|
32
|
+
elsif params[:sort] == Sort.lowest_rating.to_s
|
33
|
+
result.prepend(Sort.lowest_rating.field => Sort.lowest_rating.direction)
|
34
|
+
end
|
35
|
+
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Workarea
|
2
|
+
class ReviewSeeds
|
3
|
+
def perform
|
4
|
+
puts 'Adding reviews...'
|
5
|
+
|
6
|
+
Sidekiq::Callbacks.disable do
|
7
|
+
create_reviews_for_catalog
|
8
|
+
create_review_request_email_content
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def create_reviews_for_catalog
|
15
|
+
Workarea::Catalog::Product.all.each_by(100) do |product|
|
16
|
+
reviews = Array.new(rand(10)) { create_review(product) }
|
17
|
+
next unless reviews.size > 0
|
18
|
+
|
19
|
+
Workarea::Review.collection.insert_many(reviews.map(&:as_document))
|
20
|
+
UpdateProductReviewData.perform_async(product.id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_review(product)
|
25
|
+
Workarea::Review.new(
|
26
|
+
product_id: product.id,
|
27
|
+
user_id: BSON::ObjectId.new,
|
28
|
+
rating: rand(5) + 1,
|
29
|
+
title: Faker::Lorem.sentence,
|
30
|
+
body: Faker::Lorem.paragraph,
|
31
|
+
approved: [true, false].sample,
|
32
|
+
user_info: Faker::Internet.user_name,
|
33
|
+
verified: [true, false].sample,
|
34
|
+
created_at: rand(45).days.ago,
|
35
|
+
updated_at: Time.current
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_review_request_email_content
|
40
|
+
Content::Email.create!(
|
41
|
+
type: 'review_request',
|
42
|
+
content: <<~HTML
|
43
|
+
<h1>Let us know what you think!</h1>
|
44
|
+
<p>Your feedback is important to us.</p>
|
45
|
+
HTML
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Workarea
|
2
|
+
class CreateReview
|
3
|
+
include ActiveModel::Validations
|
4
|
+
|
5
|
+
validate :valid_review
|
6
|
+
validates :first_name, :last_name, presence: true
|
7
|
+
|
8
|
+
attr_reader :review, :user, :params
|
9
|
+
|
10
|
+
def self.for(product: nil, user: nil, params: {})
|
11
|
+
review = Review.new(
|
12
|
+
product_id: product.try(:id),
|
13
|
+
user_id: user.try(:id)
|
14
|
+
)
|
15
|
+
|
16
|
+
new(review, user: user, params: params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(review, user: nil, params: {})
|
20
|
+
@review = review
|
21
|
+
@user = user
|
22
|
+
@params = params
|
23
|
+
end
|
24
|
+
|
25
|
+
def save
|
26
|
+
update_user_attributes
|
27
|
+
update_attributes
|
28
|
+
|
29
|
+
return false unless valid?
|
30
|
+
review.save.tap { |result| update_review_requests if result }
|
31
|
+
end
|
32
|
+
|
33
|
+
def verified?
|
34
|
+
user_order_ids_with_product.any?
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def user_order_ids_with_product
|
40
|
+
return [] unless user.present?
|
41
|
+
|
42
|
+
@user_users_with_product ||=
|
43
|
+
Order.placed
|
44
|
+
.where(user_id: user.id.to_s)
|
45
|
+
.where('items.product_id' => review.product_id)
|
46
|
+
.pluck(:id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_user_attributes
|
50
|
+
return if !user.present? || user.public_info.present?
|
51
|
+
user.update_attributes(params.slice(:first_name, :last_name))
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_attributes
|
55
|
+
review.assign_attributes(
|
56
|
+
params
|
57
|
+
.slice(:rating, :body, :title)
|
58
|
+
.merge(
|
59
|
+
user_info: user_info,
|
60
|
+
first_name: first_name,
|
61
|
+
last_name: last_name,
|
62
|
+
email: email,
|
63
|
+
verified: verified?
|
64
|
+
)
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_review_requests
|
69
|
+
return unless user_order_ids_with_product.any?
|
70
|
+
Review::Request.cancel_for_orders!(user_order_ids_with_product)
|
71
|
+
end
|
72
|
+
|
73
|
+
def user_info
|
74
|
+
return user.public_info if user&.public_info.present?
|
75
|
+
|
76
|
+
"#{first_name&.first} #{last_name&.first}".strip
|
77
|
+
end
|
78
|
+
|
79
|
+
def first_name
|
80
|
+
params[:first_name].presence || user&.first_name
|
81
|
+
end
|
82
|
+
|
83
|
+
def last_name
|
84
|
+
params[:last_name].presence || user&.last_name
|
85
|
+
end
|
86
|
+
|
87
|
+
def email
|
88
|
+
params[:email].presence || user&.email
|
89
|
+
end
|
90
|
+
|
91
|
+
def valid_review
|
92
|
+
unless review.valid?
|
93
|
+
review.errors.each do |attr, error|
|
94
|
+
errors.add(attr, error)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Admin::Dashboards::ReportsViewModel, with: :reviews do
|
3
|
+
def reviews_by_product
|
4
|
+
@reviews_by_product ||=
|
5
|
+
Admin::Reports::ReviewsByProductViewModel.wrap(
|
6
|
+
Workarea::Reports::ReviewsByProduct.new(options),
|
7
|
+
options
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|