spree_emails 6.0.0.beta4 → 6.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +30 -74
- data/Rakefile +23 -0
- data/app/mailers/spree/company_mailer.rb +4 -7
- data/app/mailers/spree/customer_mailer.rb +6 -8
- data/app/mailers/spree/digital_asset_mailer.rb +18 -11
- data/app/mailers/spree/fulfillment_mailer.rb +11 -7
- data/app/mailers/spree/newsletter_mailer.rb +1 -2
- data/app/mailers/spree/order_group_mailer.rb +16 -20
- data/app/mailers/spree/order_mailer.rb +15 -20
- data/app/mailers/spree/return_mailer.rb +10 -5
- data/app/mailers/spree/seller_mailer.rb +8 -13
- data/app/models/spree/emails/amount_line.rb +32 -0
- data/app/serializers/spree/emails/address_serializer.rb +6 -0
- data/app/serializers/spree/emails/amount_line_serializer.rb +17 -0
- data/app/serializers/spree/emails/applied_promotion_serializer.rb +6 -0
- data/app/serializers/spree/emails/delivery_method_serializer.rb +6 -0
- data/app/serializers/spree/emails/delivery_rate_serializer.rb +10 -0
- data/app/serializers/spree/emails/delivery_serializer.rb +6 -0
- data/app/serializers/spree/emails/fee_serializer.rb +6 -0
- data/app/serializers/spree/emails/freight_summary_serializer.rb +6 -0
- data/app/serializers/spree/emails/fulfillment_group_serializer.rb +22 -0
- data/app/serializers/spree/emails/fulfillment_serializer.rb +19 -0
- data/app/serializers/spree/emails/gift_card_serializer.rb +6 -0
- data/app/serializers/spree/emails/line_item_serializer.rb +22 -0
- data/app/serializers/spree/emails/market_serializer.rb +6 -0
- data/app/serializers/spree/emails/option_value_serializer.rb +6 -0
- data/app/serializers/spree/emails/order_group_serializer.rb +60 -0
- data/app/serializers/spree/emails/order_serializer.rb +25 -0
- data/app/serializers/spree/emails/parcel_item_serializer.rb +36 -0
- data/app/serializers/spree/emails/payment_method_serializer.rb +6 -0
- data/app/serializers/spree/emails/payment_serializer.rb +9 -0
- data/app/serializers/spree/emails/purchase_summary_attributes.rb +41 -0
- data/app/serializers/spree/emails/purchased_item_attributes.rb +28 -0
- data/app/serializers/spree/emails/return_serializer.rb +17 -0
- data/app/serializers/spree/emails/stock_location_serializer.rb +6 -0
- data/app/services/spree/emails/samples/base.rb +79 -0
- data/app/services/spree/emails/samples/company_invitation.rb +19 -0
- data/app/services/spree/emails/samples/data_export.rb +11 -0
- data/app/services/spree/emails/samples/downloads.rb +28 -0
- data/app/services/spree/emails/samples/fulfillment.rb +33 -0
- data/app/services/spree/emails/samples/newsletter_confirmation.rb +11 -0
- data/app/services/spree/emails/samples/order.rb +22 -0
- data/app/services/spree/emails/samples/order_group.rb +22 -0
- data/app/services/spree/emails/samples/password_reset.rb +15 -0
- data/app/services/spree/emails/samples/payment_link.rb +17 -0
- data/app/services/spree/emails/samples/return.rb +29 -0
- data/app/subscribers/spree/order_email_subscriber.rb +2 -2
- data/app/subscribers/spree/order_group_email_subscriber.rb +1 -1
- data/app/subscribers/spree/return_email_subscriber.rb +2 -0
- data/app/views/spree/company_mailer/invitation_email.liquid +13 -0
- data/app/views/spree/customer_mailer/data_export_email.liquid +18 -0
- data/app/views/spree/customer_mailer/password_reset_email.liquid +14 -0
- data/app/views/spree/digital_asset_mailer/files_ready_email.liquid +23 -0
- data/app/views/spree/fulfillment_mailer/fulfilled_email.liquid +21 -0
- data/app/views/spree/newsletter_mailer/email_confirmation.liquid +13 -0
- data/app/views/spree/order_group_mailer/confirm_email.liquid +35 -0
- data/app/views/spree/order_group_mailer/store_owner_notification_email.liquid +11 -0
- data/app/views/spree/order_mailer/cancel_email.liquid +12 -0
- data/app/views/spree/order_mailer/confirm_email.liquid +12 -0
- data/app/views/spree/order_mailer/payment_link_email.liquid +12 -0
- data/app/views/spree/order_mailer/store_owner_notification_email.liquid +11 -0
- data/app/views/spree/return_mailer/refunded_email.liquid +18 -0
- data/app/views/spree/seller_mailer/approved_email.liquid +13 -0
- data/app/views/spree/seller_mailer/rejected_email.liquid +11 -0
- data/app/views/spree/seller_mailer/suspended_email.liquid +11 -0
- data/app/views/spree/shared/_fulfillment_group.liquid +20 -0
- data/app/views/spree/shared/_line_item.liquid +29 -0
- data/app/views/spree/shared/_order_summary.liquid +17 -0
- data/app/views/spree/shared/_purchase_totals.liquid +28 -0
- data/config/initializers/typelizer.rb +60 -0
- data/config/locales/ar.yml +40 -0
- data/config/locales/be.yml +37 -0
- data/config/locales/bg.yml +31 -0
- data/config/locales/ca.yml +35 -0
- data/config/locales/cs.yml +38 -0
- data/config/locales/da.yml +37 -0
- data/config/locales/de-CH.yml +11 -0
- data/config/locales/de.yml +38 -0
- data/config/locales/el.yml +37 -0
- data/config/locales/en.yml +0 -25
- data/config/locales/es-CL.yml +21 -0
- data/config/locales/es-EC.yml +22 -0
- data/config/locales/es-MX.yml +26 -0
- data/config/locales/es.yml +40 -0
- data/config/locales/et.yml +31 -0
- data/config/locales/fa.yml +37 -0
- data/config/locales/fi.yml +37 -0
- data/config/locales/fr.yml +38 -0
- data/config/locales/hu.yml +37 -0
- data/config/locales/id.yml +37 -0
- data/config/locales/it.yml +38 -0
- data/config/locales/ja.yml +36 -0
- data/config/locales/km.yml +37 -0
- data/config/locales/ko.yml +36 -0
- data/config/locales/ku.yml +37 -0
- data/config/locales/lt.yml +37 -0
- data/config/locales/lv.yml +39 -0
- data/config/locales/nb.yml +37 -0
- data/config/locales/ne.yml +37 -0
- data/config/locales/nl.yml +38 -0
- data/config/locales/pl.yml +39 -0
- data/config/locales/pt-BR.yml +34 -0
- data/config/locales/pt.yml +34 -0
- data/config/locales/ro.yml +37 -0
- data/config/locales/ru.yml +38 -0
- data/config/locales/sk.yml +31 -0
- data/config/locales/sl-SI.yml +31 -0
- data/config/locales/sv.yml +37 -0
- data/config/locales/th.yml +37 -0
- data/config/locales/tr.yml +38 -0
- data/config/locales/uk.yml +42 -0
- data/config/locales/vi.yml +35 -0
- data/config/locales/zh-CN.yml +38 -0
- data/config/locales/zh-TW.yml +40 -0
- data/lib/spree/emails/engine.rb +27 -3
- data/lib/spree/emails/previews/company_preview.rb +10 -0
- data/lib/spree/emails/previews/customer_preview.rb +4 -0
- data/lib/spree/emails/previews/digital_asset_preview.rb +20 -0
- metadata +107 -55
- data/app/helpers/spree/base_helper.rb +0 -45
- data/app/helpers/spree/digital_asset_helper.rb +0 -16
- data/app/helpers/spree/fulfillment_helper.rb +0 -12
- data/app/helpers/spree/mail_helper.rb +0 -10
- data/app/views/spree/company_mailer/invitation_email.html.erb +0 -8
- data/app/views/spree/company_mailer/invitation_email.text.erb +0 -11
- data/app/views/spree/customer_mailer/data_export_email.html.erb +0 -12
- data/app/views/spree/customer_mailer/data_export_email.text.erb +0 -9
- data/app/views/spree/customer_mailer/password_reset_email.html.erb +0 -10
- data/app/views/spree/customer_mailer/password_reset_email.text.erb +0 -13
- data/app/views/spree/digital_asset_mailer/files_ready_email.html.erb +0 -20
- data/app/views/spree/digital_asset_mailer/files_ready_email.text.erb +0 -10
- data/app/views/spree/fulfillment_mailer/fulfilled_email.html.erb +0 -22
- data/app/views/spree/fulfillment_mailer/fulfilled_email.text.erb +0 -18
- data/app/views/spree/newsletter_mailer/email_confirmation.html.erb +0 -12
- data/app/views/spree/newsletter_mailer/email_confirmation.text.erb +0 -9
- data/app/views/spree/order_group_mailer/confirm_email.html.erb +0 -38
- data/app/views/spree/order_group_mailer/confirm_email.text.erb +0 -26
- data/app/views/spree/order_group_mailer/store_owner_notification_email.html.erb +0 -14
- data/app/views/spree/order_group_mailer/store_owner_notification_email.text.erb +0 -11
- data/app/views/spree/order_mailer/cancel_email.html.erb +0 -12
- data/app/views/spree/order_mailer/cancel_email.text.erb +0 -13
- data/app/views/spree/order_mailer/confirm_email.html.erb +0 -12
- data/app/views/spree/order_mailer/confirm_email.text.erb +0 -13
- data/app/views/spree/order_mailer/payment_link_email.html.erb +0 -11
- data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -11
- data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -13
- data/app/views/spree/return_mailer/refunded_email.html.erb +0 -22
- data/app/views/spree/return_mailer/refunded_email.text.erb +0 -20
- data/app/views/spree/seller_mailer/approved_email.html.erb +0 -8
- data/app/views/spree/seller_mailer/approved_email.text.erb +0 -8
- data/app/views/spree/seller_mailer/rejected_email.html.erb +0 -6
- data/app/views/spree/seller_mailer/rejected_email.text.erb +0 -7
- data/app/views/spree/seller_mailer/suspended_email.html.erb +0 -6
- data/app/views/spree/seller_mailer/suspended_email.text.erb +0 -7
- data/app/views/spree/shared/_fulfillment_group_section.html.erb +0 -37
- data/app/views/spree/shared/_fulfillment_group_section.text.erb +0 -12
- data/app/views/spree/shared/_item_thumbnail_link.html.erb +0 -18
- data/app/views/spree/shared/_order_summary_section.html.erb +0 -20
- data/app/views/spree/shared/_po_number.text.erb +0 -6
- data/app/views/spree/shared/_purchase_totals.html.erb +0 -62
- data/app/views/spree/shared/_purchase_totals.text.erb +0 -24
- data/app/views/spree/shared/_purchased_items_table.html.erb +0 -41
- data/app/views/spree/shared/_purchased_items_table.text.erb +0 -28
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -24
- data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -3
- data/app/views/spree/shared/purchased_items_table/_summary_row.html.erb +0 -14
- data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -4
- data/config/i18n-tasks.yml +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 460c53ff1f08bac66ed9a76caadbdedf216833d3faa0bf2dd7b2e6331f72a6a1
|
|
4
|
+
data.tar.gz: 73c0209ebcd6c95e34f61d27c6d4b808a3b86451f4c2f7b3b9ca995f65418e71
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6ced0f9e3ef9421db913ec441cdc8b90cd2bc731c2cab7538e99bc29e358f0565903ed7a13cf11ca8931438c6315dce67479b061ee20f1e168f2e4eab2d8ec62
|
|
7
|
+
data.tar.gz: 455ae9a4a57332fa838eeedec373640d356fdbf7ec5f623cd249054bfdca31f91318d1fde93338307da3de5ed270613725e8070adc5d17e4122117554518efd2
|
data/README.md
CHANGED
|
@@ -8,11 +8,11 @@ Spree Emails provides transactional email templates and mailers for Spree Commer
|
|
|
8
8
|
|
|
9
9
|
This gem includes:
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
- **Mailers** for order confirmation, cancellation and payment links, multi-seller purchase confirmations, fulfillment notices, refunds, digital downloads, customer password resets and data exports, newsletter confirmation, company invitations and seller status changes
|
|
12
|
+
- **Event subscribers** that send them when store events happen
|
|
13
|
+
- **Liquid templates** written in MJML, one per email, that you can override
|
|
14
|
+
|
|
15
|
+
Staff emails (password resets, invitations, import and export results, disabled webhooks) live in `spree_core` and render the same way.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -20,22 +20,6 @@ This gem includes:
|
|
|
20
20
|
bundle add spree_emails
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Email Types
|
|
24
|
-
|
|
25
|
-
### Order Emails
|
|
26
|
-
|
|
27
|
-
- **Order Confirmation** - Sent when an order is completed
|
|
28
|
-
- **Order Cancellation** - Sent when an order is cancelled
|
|
29
|
-
|
|
30
|
-
### Shipment Emails
|
|
31
|
-
|
|
32
|
-
- **Shipment Notification** - Sent when a shipment is shipped
|
|
33
|
-
- **Delivery Confirmation** - Sent when tracking shows delivered
|
|
34
|
-
|
|
35
|
-
### Reimbursement Emails
|
|
36
|
-
|
|
37
|
-
- **Refund Notification** - Sent when a reimbursement is processed
|
|
38
|
-
|
|
39
23
|
## Configuration
|
|
40
24
|
|
|
41
25
|
Transactional emails are controlled per-store via the `send_consumer_transactional_emails` preference. This can be configured in the admin dashboard under Store Settings, or programmatically:
|
|
@@ -69,72 +53,44 @@ config.action_mailer.smtp_settings = {
|
|
|
69
53
|
|
|
70
54
|
## Customization
|
|
71
55
|
|
|
72
|
-
### Overriding
|
|
73
|
-
|
|
74
|
-
Copy email templates to your application:
|
|
56
|
+
### Overriding templates
|
|
75
57
|
|
|
76
|
-
|
|
77
|
-
# Copy all email templates
|
|
78
|
-
cp -r $(bundle show spree_emails)/app/views/spree/mailer app/views/spree/
|
|
58
|
+
Every email renders from a Liquid template at its Rails view path. To change one, create the file at the same path in your app — for example `app/views/spree/order_mailer/confirm_email.liquid` — starting from the copy in this gem's `app/views`. The layout around every email is `app/views/layouts/spree/base_mailer.liquid`.
|
|
79
59
|
|
|
80
|
-
|
|
81
|
-
cp $(bundle show spree_emails)/app/views/spree/mailer/order_mailer/confirm_email.html.erb \
|
|
82
|
-
app/views/spree/mailer/order_mailer/
|
|
83
|
-
```
|
|
60
|
+
Templates read plain data from serializers, never models: see the [email templates guide](https://spreecommerce.org/docs/developer/customization/emails) for the layout, partials, filters and escaping, and the [variable reference](https://spreecommerce.org/docs/developer/customization/email-variables) for what each template receives.
|
|
84
61
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
app/views/spree/mailer/
|
|
89
|
-
├── order_mailer/
|
|
90
|
-
│ ├── confirm_email.html.erb
|
|
91
|
-
│ ├── confirm_email.text.erb
|
|
92
|
-
│ ├── cancel_email.html.erb
|
|
93
|
-
│ └── cancel_email.text.erb
|
|
94
|
-
├── shipment_mailer/
|
|
95
|
-
│ ├── shipped_email.html.erb
|
|
96
|
-
│ └── shipped_email.text.erb
|
|
97
|
-
└── reimbursement_mailer/
|
|
98
|
-
├── reimbursement_email.html.erb
|
|
99
|
-
└── reimbursement_email.text.erb
|
|
100
|
-
```
|
|
62
|
+
Mailers of your own that render ERB views keep working, wrapped in the same layout.
|
|
101
63
|
|
|
102
|
-
###
|
|
64
|
+
### Adding new email types
|
|
103
65
|
|
|
104
|
-
|
|
66
|
+
Extend Spree's base mailer and render a Liquid template at the action's view path, passing the data it needs:
|
|
105
67
|
|
|
106
68
|
```ruby
|
|
107
|
-
# app/mailers/spree/
|
|
69
|
+
# app/mailers/spree/custom_mailer.rb
|
|
108
70
|
module Spree
|
|
109
|
-
|
|
110
|
-
def
|
|
111
|
-
@
|
|
112
|
-
super
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
private
|
|
71
|
+
class CustomMailer < BaseMailer
|
|
72
|
+
def welcome_email(customer, store)
|
|
73
|
+
@current_store = store
|
|
116
74
|
|
|
117
|
-
|
|
118
|
-
|
|
75
|
+
with_store_locale(@current_store) do
|
|
76
|
+
mail_template({ customer: email_data(customer, Spree.api.customer_serializer) }, to: customer.email)
|
|
77
|
+
end
|
|
119
78
|
end
|
|
120
79
|
end
|
|
121
80
|
end
|
|
122
|
-
|
|
123
|
-
Spree::OrderMailer.prepend(Spree::OrderMailerDecorator)
|
|
124
81
|
```
|
|
125
82
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
end
|
|
83
|
+
And its template, `app/views/spree/custom_mailer/welcome_email.liquid` (the front matter must open the file):
|
|
84
|
+
|
|
85
|
+
```liquid
|
|
86
|
+
---
|
|
87
|
+
subject: "Welcome to {{ store.name }}"
|
|
88
|
+
---
|
|
89
|
+
<mj-section>
|
|
90
|
+
<mj-column css-class="hero">
|
|
91
|
+
<mj-text mj-class="heading">Welcome, {{ customer.first_name }}!</mj-text>
|
|
92
|
+
</mj-column>
|
|
93
|
+
</mj-section>
|
|
138
94
|
```
|
|
139
95
|
|
|
140
96
|
## Event Integration
|
|
@@ -152,7 +108,7 @@ module MyApp
|
|
|
152
108
|
user = Spree.customer_class.find_by(id: user_id)
|
|
153
109
|
return unless user
|
|
154
110
|
|
|
155
|
-
Spree::CustomMailer.welcome_email(user).deliver_later
|
|
111
|
+
Spree::CustomMailer.welcome_email(user, Spree::Store.default).deliver_later
|
|
156
112
|
end
|
|
157
113
|
end
|
|
158
114
|
end
|
data/Rakefile
CHANGED
|
@@ -13,3 +13,26 @@ task :test_app do
|
|
|
13
13
|
ENV['LIB_NAME'] = 'spree/emails'
|
|
14
14
|
Rake::Task['common:test_app'].invoke
|
|
15
15
|
end
|
|
16
|
+
|
|
17
|
+
namespace :typelizer do
|
|
18
|
+
desc 'Generate TypeScript types for every SDK, the email template types included'
|
|
19
|
+
task :generate do
|
|
20
|
+
ENV['RAILS_ENV'] ||= 'test'
|
|
21
|
+
ENV['DISABLE_TYPELIZER'] = 'false'
|
|
22
|
+
ENV['ENABLE_TYPELIZER'] = '1'
|
|
23
|
+
|
|
24
|
+
dummy = File.expand_path('spec/dummy/config/environment.rb', __dir__)
|
|
25
|
+
abort 'Build the test app first: cd spree/emails && bundle exec rake test_app' unless File.exist?(dummy)
|
|
26
|
+
|
|
27
|
+
require dummy
|
|
28
|
+
require 'spree/api/typelizer_generation'
|
|
29
|
+
|
|
30
|
+
Spree::Api::TypelizerGeneration.call([
|
|
31
|
+
Spree::Api::Engine.root.join('app/serializers/spree/api/v3'),
|
|
32
|
+
Spree::Emails::Engine.root.join('app/serializers/spree/emails'),
|
|
33
|
+
Spree::Core::Engine.root.join('app/serializers/spree/emails')
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
puts 'Generated types → packages/sdk, packages/admin-sdk and packages/seller-sdk'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -4,8 +4,6 @@ module Spree
|
|
|
4
4
|
# invitation, this is transactional, not marketing: the no-welcome-email
|
|
5
5
|
# rule on customer creation is untouched.
|
|
6
6
|
class CompanyMailer < BaseMailer
|
|
7
|
-
helper Spree::MailHelper
|
|
8
|
-
|
|
9
7
|
# The invite carries the plaintext token; the storefront owns the
|
|
10
8
|
# acceptance page, so the link resolves against the store URL like other
|
|
11
9
|
# customer-facing links.
|
|
@@ -19,14 +17,13 @@ module Spree
|
|
|
19
17
|
return message.perform_deliveries = false unless @invitation.reload.pending?
|
|
20
18
|
|
|
21
19
|
@company = @invitation.company
|
|
22
|
-
store = @company.store
|
|
20
|
+
store = @current_store = @company.store
|
|
23
21
|
@accept_url = append_token(invitation_base_url(store), @invitation.token)
|
|
24
22
|
|
|
25
23
|
with_store_locale(store) do
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
store_url: store.storefront_url
|
|
24
|
+
mail_template(
|
|
25
|
+
{ company: email_data(@company, Spree.api.company_serializer), accept_url: @accept_url },
|
|
26
|
+
to: @invitation.email, store_url: store.storefront_url
|
|
30
27
|
)
|
|
31
28
|
end
|
|
32
29
|
end
|
|
@@ -10,10 +10,9 @@ module Spree
|
|
|
10
10
|
@reset_url = append_token(base_url, reset_token)
|
|
11
11
|
|
|
12
12
|
with_store_locale(store) do
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
store_url: store.storefront_url
|
|
13
|
+
mail_template(
|
|
14
|
+
{ customer: email_data(user, Spree.api.customer_serializer), reset_url: @reset_url },
|
|
15
|
+
to: user.email, store_url: store.storefront_url
|
|
17
16
|
)
|
|
18
17
|
end
|
|
19
18
|
end
|
|
@@ -31,10 +30,9 @@ module Spree
|
|
|
31
30
|
@expires_at = data_request.expires_at
|
|
32
31
|
|
|
33
32
|
with_store_locale(@current_store) do
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
store_url: @current_store.storefront_url
|
|
33
|
+
mail_template(
|
|
34
|
+
{ download_url: @download_url, expires_at: @expires_at&.iso8601 },
|
|
35
|
+
to: data_request.email, store_url: @current_store.storefront_url
|
|
38
36
|
)
|
|
39
37
|
end
|
|
40
38
|
end
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class DigitalAssetMailer < BaseMailer
|
|
3
|
-
helper Spree::MailHelper
|
|
4
|
-
helper Spree::DigitalAssetHelper
|
|
5
|
-
|
|
6
3
|
# Sent once an order's downloads are ready. Kept separate from the order
|
|
7
4
|
# confirmation so it can be re-sent on its own, and so a storefront that
|
|
8
5
|
# replaces the confirmation email does not silently lose the links.
|
|
@@ -13,17 +10,27 @@ module Spree
|
|
|
13
10
|
@digital_links = @order.digital_links.includes(digital_asset: { attachment_attachment: :blob })
|
|
14
11
|
return if @digital_links.empty?
|
|
15
12
|
|
|
16
|
-
current_store = @order.store
|
|
17
13
|
@download_host = current_store.formatted_url
|
|
18
14
|
with_store_locale(current_store, @order.locale) do
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@order.
|
|
23
|
-
resend: resend
|
|
15
|
+
mail_template(
|
|
16
|
+
{ order: email_data(@order, Spree::Emails::OrderSerializer),
|
|
17
|
+
downloads: downloads, resend: resend },
|
|
18
|
+
to: @order.email, store_url: current_store.storefront_url
|
|
24
19
|
)
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
# Download URLs carry each link's bearer token, so they are built here
|
|
26
|
+
# rather than serialized. They point at the backend, not the storefront.
|
|
27
|
+
def downloads
|
|
28
|
+
@digital_links.map do |digital_link|
|
|
29
|
+
{
|
|
30
|
+
filename: digital_link.filename.to_s,
|
|
31
|
+
url: Spree::Api::DigitalLinkUrls.download_url(digital_link, @download_host),
|
|
32
|
+
expires_at: digital_link.expires_at&.iso8601
|
|
33
|
+
}
|
|
27
34
|
end
|
|
28
35
|
end
|
|
29
36
|
end
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class FulfillmentMailer < BaseMailer
|
|
3
|
-
helper Spree::MailHelper
|
|
4
|
-
helper Spree::FulfillmentHelper
|
|
5
|
-
|
|
6
3
|
def fulfilled_email(fulfillment, resend = false)
|
|
7
4
|
@fulfillment = fulfillment.respond_to?(:id) ? fulfillment : Spree::Fulfillment.find(fulfillment)
|
|
8
5
|
@order = @fulfillment.order
|
|
9
|
-
current_store = @fulfillment.store
|
|
6
|
+
@current_store = @fulfillment.store
|
|
7
|
+
|
|
10
8
|
with_store_locale(current_store, @order.locale) do
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
mail_template(
|
|
10
|
+
{
|
|
11
|
+
fulfillment: email_data(@fulfillment, Spree::Emails::FulfillmentSerializer),
|
|
12
|
+
order: email_data(@order, Spree::Emails::OrderSerializer),
|
|
13
|
+
resend: resend
|
|
14
|
+
},
|
|
15
|
+
template: 'spree/fulfillment_mailer/fulfilled_email',
|
|
16
|
+
to: @order.email, store_url: current_store.storefront_url
|
|
17
|
+
)
|
|
14
18
|
end
|
|
15
19
|
end
|
|
16
20
|
end
|
|
@@ -9,9 +9,8 @@ module Spree
|
|
|
9
9
|
base_url = redirect_url.presence || store.storefront_url
|
|
10
10
|
@confirm_email_url = append_token(base_url, @subscriber.verification_token)
|
|
11
11
|
with_store_locale(store) do
|
|
12
|
-
|
|
12
|
+
mail_template({ confirmation_url: @confirm_email_url }, to: @subscriber.email)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
|
-
|
|
16
15
|
end
|
|
17
16
|
end
|
|
@@ -12,34 +12,16 @@ module Spree
|
|
|
12
12
|
# email unchanged, and a storefront replacing one document should not have to
|
|
13
13
|
# inherit the other.
|
|
14
14
|
class OrderGroupMailer < BaseMailer
|
|
15
|
-
helper Spree::MailHelper
|
|
16
|
-
|
|
17
15
|
# @param order_group [Spree::OrderGroup, Integer, String] record or id
|
|
18
16
|
# @param resend [Boolean] prefixes the subject, for an admin re-send
|
|
19
17
|
def confirm_email(order_group, resend = false)
|
|
20
18
|
@order_group = find_order_group(order_group)
|
|
21
|
-
|
|
22
|
-
# off @order and would otherwise fall back to the default store — the
|
|
23
|
-
# wrong store's name, logo and footer on a multi-store install.
|
|
24
|
-
@current_store = @order_group.store
|
|
25
|
-
|
|
26
|
-
with_store_locale(@current_store, @order_group.locale) do
|
|
27
|
-
subject = order_email_subject(
|
|
28
|
-
@current_store, Spree.t('order_group_mailer.confirm_email.subject'), @order_group.number, resend: resend
|
|
29
|
-
)
|
|
30
|
-
mail(to: @order_group.email, subject: subject, store_url: @current_store.storefront_url)
|
|
31
|
-
end
|
|
19
|
+
deliver_order_group_email(to: @order_group.email, locale: @order_group.locale, resend: resend)
|
|
32
20
|
end
|
|
33
21
|
|
|
34
22
|
def store_owner_notification_email(order_group)
|
|
35
23
|
@order_group = find_order_group(order_group)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
with_store_locale(@current_store) do
|
|
39
|
-
subject = Spree.t('order_group_mailer.store_owner_notification_email.subject', store_name: @current_store.name)
|
|
40
|
-
mail(to: @current_store.new_order_notifications_email, subject: subject,
|
|
41
|
-
store_url: @current_store.storefront_url)
|
|
42
|
-
end
|
|
24
|
+
deliver_order_group_email(to: @order_group.store.new_order_notifications_email)
|
|
43
25
|
end
|
|
44
26
|
|
|
45
27
|
private
|
|
@@ -47,5 +29,19 @@ module Spree
|
|
|
47
29
|
def find_order_group(order_group)
|
|
48
30
|
order_group.respond_to?(:id) ? order_group : Spree::OrderGroup.find(order_group)
|
|
49
31
|
end
|
|
32
|
+
|
|
33
|
+
def deliver_order_group_email(to:, locale: nil, resend: false)
|
|
34
|
+
# Assigned rather than left to BaseMailer#current_store, which memoizes
|
|
35
|
+
# off @order and would otherwise fall back to the default store — the
|
|
36
|
+
# wrong store's name, logo and footer on a multi-store install.
|
|
37
|
+
@current_store = @order_group.store
|
|
38
|
+
|
|
39
|
+
with_store_locale(@current_store, locale) do
|
|
40
|
+
mail_template(
|
|
41
|
+
{ order_group: email_data(@order_group, Spree::Emails::OrderGroupSerializer), resend: resend },
|
|
42
|
+
to: to, store_url: @current_store.storefront_url
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
50
46
|
end
|
|
51
47
|
end
|
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class OrderMailer < BaseMailer
|
|
3
|
-
helper Spree::MailHelper
|
|
4
|
-
|
|
5
3
|
def confirm_email(order, resend = false)
|
|
6
4
|
@order = order.respond_to?(:id) ? order : Spree::Order.find(order)
|
|
7
|
-
|
|
8
|
-
with_store_locale(current_store, @order.locale) do
|
|
9
|
-
subject = order_email_subject(current_store, Spree.t('order_mailer.confirm_email.subject'), @order.number, resend: resend)
|
|
10
|
-
mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
|
|
11
|
-
end
|
|
5
|
+
deliver_order_email(to: @order.email, locale: @order.locale, resend: resend)
|
|
12
6
|
end
|
|
13
7
|
|
|
14
8
|
def store_owner_notification_email(order)
|
|
15
9
|
@order = order.respond_to?(:id) ? order : Spree::Order.find(order)
|
|
16
|
-
current_store
|
|
17
|
-
with_store_locale(current_store) do
|
|
18
|
-
subject = Spree.t('order_mailer.store_owner_notification_email.subject', store_name: current_store.name)
|
|
19
|
-
mail(to: current_store.new_order_notifications_email, subject: subject, store_url: current_store.storefront_url)
|
|
20
|
-
end
|
|
10
|
+
deliver_order_email(to: current_store.new_order_notifications_email)
|
|
21
11
|
end
|
|
22
12
|
|
|
23
13
|
def cancel_email(order, resend = false)
|
|
24
14
|
@order = order.respond_to?(:id) ? order : Spree::Order.find(order)
|
|
25
|
-
|
|
26
|
-
with_store_locale(current_store, @order.locale) do
|
|
27
|
-
subject = order_email_subject(current_store, Spree.t('order_mailer.cancel_email.subject'), @order.number, resend: resend)
|
|
28
|
-
mail(to: @order.email, subject: subject, store_url: current_store.storefront_url)
|
|
29
|
-
end
|
|
15
|
+
deliver_order_email(to: @order.email, locale: @order.locale, resend: resend)
|
|
30
16
|
end
|
|
31
17
|
|
|
32
18
|
def payment_link_email(order_id)
|
|
33
19
|
@order = Spree::Order.incomplete.not_canceled.find(order_id)
|
|
34
20
|
@current_store = @order.store
|
|
21
|
+
# Carries the order token, so it is built here and never serialized.
|
|
35
22
|
@checkout_payment_url = URI.join(@current_store.storefront_url, "/checkout/#{@order.token}/payment").to_s
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
deliver_order_email(to: @order.email, locale: @order.locale, payment_url: @checkout_payment_url)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def deliver_order_email(to:, locale: nil, **assigns)
|
|
30
|
+
with_store_locale(current_store, locale) do
|
|
31
|
+
mail_template(
|
|
32
|
+
{ order: email_data(@order, Spree::Emails::OrderSerializer), resend: false }.merge(assigns),
|
|
33
|
+
to: to, store_url: current_store.storefront_url
|
|
34
|
+
)
|
|
40
35
|
end
|
|
41
36
|
end
|
|
42
37
|
end
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class ReturnMailer < BaseMailer
|
|
3
|
-
helper Spree::MailHelper
|
|
4
|
-
|
|
5
3
|
# Tells the customer their returned items were refunded. Replaces the
|
|
6
4
|
# reimbursement email dropped with the ReturnAuthorization chain in 6.0.
|
|
7
5
|
def refunded_email(return_record, resend = false)
|
|
8
6
|
@return = return_record.respond_to?(:id) ? return_record : Spree::Return.find(return_record)
|
|
9
7
|
@order = @return.order
|
|
10
|
-
current_store = @return.store || Spree::Store.default
|
|
8
|
+
@current_store = @return.store || Spree::Store.default
|
|
9
|
+
|
|
11
10
|
with_store_locale(current_store, @order.locale) do
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
mail_template(
|
|
12
|
+
{
|
|
13
|
+
return: email_data(@return, Spree::Emails::ReturnSerializer),
|
|
14
|
+
order: email_data(@order, Spree::Emails::OrderSerializer),
|
|
15
|
+
resend: resend
|
|
16
|
+
},
|
|
17
|
+
to: @order.email, store_url: current_store.storefront_url
|
|
18
|
+
)
|
|
14
19
|
end
|
|
15
20
|
end
|
|
16
21
|
end
|
|
@@ -6,8 +6,6 @@ module Spree
|
|
|
6
6
|
# is a lot of mail about something staff can already see in the dashboard.
|
|
7
7
|
# Marketplace-side notifications ride the event and webhook surface instead.
|
|
8
8
|
class SellerMailer < BaseMailer
|
|
9
|
-
helper Spree::MailHelper
|
|
10
|
-
|
|
11
9
|
# @param seller [Spree::Seller, Integer]
|
|
12
10
|
def approved_email(seller)
|
|
13
11
|
@seller = load_seller(seller)
|
|
@@ -15,7 +13,7 @@ module Spree
|
|
|
15
13
|
# so a hosted dashboard, a dev Vite server and a mounted build all work.
|
|
16
14
|
@dashboard_url = Spree::Stores::DashboardUrl.call(store: store).presence
|
|
17
15
|
|
|
18
|
-
deliver_to_seller
|
|
16
|
+
deliver_to_seller
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
# Carries no reason: the operator's note is an internal record, and a
|
|
@@ -23,13 +21,13 @@ module Spree
|
|
|
23
21
|
def suspended_email(seller)
|
|
24
22
|
@seller = load_seller(seller)
|
|
25
23
|
|
|
26
|
-
deliver_to_seller
|
|
24
|
+
deliver_to_seller
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
def rejected_email(seller)
|
|
30
28
|
@seller = load_seller(seller)
|
|
31
29
|
|
|
32
|
-
deliver_to_seller
|
|
30
|
+
deliver_to_seller
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
private
|
|
@@ -49,18 +47,15 @@ module Spree
|
|
|
49
47
|
(@seller.users.pluck(:email) << @seller.contact_email).compact_blank.uniq(&:downcase)
|
|
50
48
|
end
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
# the block would render it in whatever locale the job happens to run
|
|
54
|
-
# under, so a seller could get an English subject over a German email.
|
|
55
|
-
def deliver_to_seller(subject_key)
|
|
50
|
+
def deliver_to_seller
|
|
56
51
|
addresses = recipients
|
|
57
52
|
return message.perform_deliveries = false if addresses.empty?
|
|
58
53
|
|
|
54
|
+
@current_store = store
|
|
59
55
|
with_store_locale(store) do
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
store_url: store.storefront_url
|
|
56
|
+
mail_template(
|
|
57
|
+
{ seller: email_data(@seller, Spree.api.seller_serializer), dashboard_url: @dashboard_url },
|
|
58
|
+
to: addresses, store_url: store.storefront_url
|
|
64
59
|
)
|
|
65
60
|
end
|
|
66
61
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Emails
|
|
3
|
+
# One labelled amount on an email's summary: a promotion, a manual
|
|
4
|
+
# discount, a delivery rate or a fee, with rows sharing a label summed.
|
|
5
|
+
class AmountLine
|
|
6
|
+
include ActiveModel::Model
|
|
7
|
+
include ActiveModel::Attributes
|
|
8
|
+
extend Spree::DisplayMoney
|
|
9
|
+
|
|
10
|
+
attribute :label, :string
|
|
11
|
+
attribute :amount, :decimal
|
|
12
|
+
attribute :currency, :string
|
|
13
|
+
|
|
14
|
+
money_methods :amount
|
|
15
|
+
|
|
16
|
+
# Sums records sharing a label into one line each.
|
|
17
|
+
#
|
|
18
|
+
# @param records [Enumerable] the rows to sum
|
|
19
|
+
# @param currency [String]
|
|
20
|
+
# @param label [Symbol, Proc] names each row
|
|
21
|
+
# @param amount [Symbol] the method giving each row's amount
|
|
22
|
+
# @param keep_zero [Boolean] whether a line coming to zero is kept
|
|
23
|
+
# @return [Array<Spree::Emails::AmountLine>]
|
|
24
|
+
def self.group(records, currency:, label: :label, amount: :amount, keep_zero: false)
|
|
25
|
+
records.to_a.group_by(&label).filter_map do |name, rows|
|
|
26
|
+
sum = rows.sum { |row| row.public_send(amount).to_d }
|
|
27
|
+
new(label: name, amount: sum, currency: currency) if keep_zero || !sum.zero?
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Emails
|
|
3
|
+
class AmountLineSerializer
|
|
4
|
+
include Alba::Resource
|
|
5
|
+
|
|
6
|
+
attributes :label
|
|
7
|
+
|
|
8
|
+
attribute :display_amount do |line|
|
|
9
|
+
line.display_amount.to_s
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attribute :amount do |line|
|
|
13
|
+
line.amount.to_s
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Emails
|
|
3
|
+
class DeliveryRateSerializer < Spree::Api::V3::DeliveryRateSerializer
|
|
4
|
+
typelize freight_summary: [:EmailFreightSummary, nullable: true]
|
|
5
|
+
|
|
6
|
+
one :freight_summary, resource: Spree::Emails::FreightSummarySerializer
|
|
7
|
+
one :delivery_method, resource: Spree::Emails::DeliveryMethodSerializer
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|