고객이 Spree Commerce를 통해 품절 제품 구독 가능
37055 단어 railsjavascriptspreecommerceruby
때때로 고객이 구매하고자 하는 상품이 재고가 있을 때 그들에게 통지하는 것은 좋은 일이다.사실 그들은 다른 곳으로 가서 구매할 것이다. 그렇지?만약 다른 곳에 더 싼 것이 있다면, 그들은 거의 다른 곳으로 가서 구매할 것이다.그러나 만약에 당신이 판매하는 제품이 유일무이하고 품질이 더 좋거나 고객이 당신의 지지를 좋아하거나 전체적으로 당신을 좋아한다면 어떻게 해야 합니까?우리는 품절 전자 우편 통지 시스템을 실시할 것이다.나는 통지라고 부른다.그것의 묘미는 우리가 좋아하는 방식에 따라 변수를 명명하거나 정의할 수 있다는 데 있다😂
시작하기 전에 Spree가 제품 수를 어떻게 업데이트하는지 살펴보겠습니다.대부분의 기업이 '재고 추적' 을 사용하지 않음에도 불구하고 '재고량' 은 우리가 원하는 목표이다.우리는 이후의 해석에서 이 문제를 토론할 것이다.
만약 당신의 업무가 재고에 의존한다면, 이 강좌는 당신에게 적합합니다.
StockItemsController에서 우리는 세 가지 동작을 보고 싶다.
업데이트
재고 품목을 업데이트할 때는 수량이 0을 초과하면 모든 고객에게 이메일을 보내야 합니다.🙄
만들다
마찬가지로 재고 이동을 추가할 때 모든 고객에게 이메일을 보냅니다.
부수다
우리는 더 이상 재고를 추적하지 않기로 결정했다.이렇게 하면 카트에 추가 버튼이 활성화되므로 왜 모든 고객에게 이메일을 보내지 않습니까?
# see https://github.com/spree/spree/blob/master/backend/app/controllers/spree/admin/stock_items_controller.rb
module Spree
module Admin
module StockItemsControllerDecorator
def self.prepended(base)
base.before_action :process_notifiees_on_stock_item, only: :update
# We have not taken into account should stock_movement.save fails.
# see https://github.com/spree/spree/blob/master/backend/app/controllers/spree/admin/stock_items_controller.rb#L13
base.before_action :process_notifiees_on_stock_movement, only: :create
base.before_action :notify_notifiees, only: :destroy
end
private
# We've made the executive decision by not keeping stocks.
# Alert all customers that the product is available to purchase.
def notify_notifiees
variant_id = stock_item.variant.id
email_all_notifiees(variant_id)
end
def process_notifiees_on_stock_movement
quantity = params[:stock_movement][:quantity].to_i
variant_id = params[:variant_id]
if quantity > 0
email_all_notifiees(variant_id)
end
end
def email_all_notifiees(variant_id)
product_id = Spree::Variant.find(variant_id).product.id
notifiees = lookup_notifiees_by(product_id)
send_notification_email(notifiees)
# We said we'd delete their email address
notifiees.destroy_all
end
def process_notifiees_on_stock_item
# Backorderable: boolean
# stock_item.backorderable
# Number of items in stock: integer
# stock_item.count_on_hand
if stock_item.count_on_hand > 0
variant_id = stock_item.variant.id
email_all_notifiees(variant_id)
end
end
def lookup_notifiees_by(product_id)
ProductNotification.where(product_id: product_id)
end
def send_notification_email(notifiees)
if notifiees.present?
emails_to_send = notifiees.pluck(:email)
# send the email
end
end
end
end
end
::Spree::Admin::StockItemsController.prepend Spree::Admin::StockItemsControllerDecorator if ::Spree::Admin::StockItemsController.included_modules.exclude?(Spree::Admin::StockItemsControllerDecorator)
이런 논리는 고객이 어디에서 변형을 주문할지 고려하지 않고 제품 자체를 고려한다.이상적인 상황에서, 당신은 이 코드를 당신의 업무 논리에 맞게 바꾸기를 원합니다.My online store 서로 다른 유형의 변체를 사용하지 않지만, 내가 깊이 들어가면 변체를 사용할 수 있다.코드에서 너는 내가 있다는 것을 알아차릴 것이다.
ProductNotification
ProductNotification
모델은 내가'알림'을 저장하는 곳이다.전자 우편 주소, 제품 id (변형을 저장하고 싶을 수도 있고 변경할 수도 있습니다), 사용자 id (선택 가능) 를 저장했습니다.마이그레이션:
class CreateProductNotifications < ActiveRecord::Migration[6.1]
def change
create_table :product_notifications do |t|
t.references :user, null: true
t.references :product
t.string :email
t.timestamps
end
end
end
모델 번호:
class ProductNotification < ApplicationRecord
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
belongs_to :user, class_name: 'Spree::User', optional: true
belongs_to :product, class_name: 'Spree::Product'
end
user
는 선택할 수 있습니다. 왜냐하면 저는 내빈도 구독하기를 원하기 때문입니다. 사용자가 로그인하면 사용자 id를 사용할 것입니다.Spree 제품 모델
module Spree
module ProductDecorator
def self.prepended(base)
base.has_many :product_notifications, class_name: 'ProductNotification', foreign_key: 'product_id', dependent: :destroy
end
end
end
::Spree::Product.prepend Spree::ProductDecorator if ::Spree::Product.included_modules.exclude?(Spree::ProductDecorator)
컨트롤러:
class Spree::Products::NotifyController < ApplicationController
include ActionView::Helpers::TextHelper
layout false
def notify_me
email = strip_tags(notify_params[:email])
@notif = ProductNotification.find_or_create_by(email: email) do |perm|
perm.product_id = notify_params[:product_id]
perm.user_id = notify_params[:user_id]
end
if @notif.save
@notif_saved = true
else
@notif_saved = false
end
end
private
def notify_params
params.require(:product_notification).permit(
:email,
:product_id
).tap do |p|
# Overkill to have this here, I know.
p[:user_id] = spree_current_user ? spree_current_user.id : nil
end
end
end
경로
나는 모든 노선을
Spree::Core::Engine.add_routes do
블록 아래에 저장할 것이다.[..]
Spree::Core::Engine.add_routes do
[..]
post '/products/notify', to: 'products/notify#notify_me', as: 'product_notify'
[..]
end
프런트엔드
프런트엔드에 대해 수정
_cart_form.html
했는데 제공할 수 없을 때 알림 양식이 표시됩니다.[..]
<% if !@product.can_supply? %>
<%= render 'notify_me_when_available' %>
<% end %>
및 내부_notify_me_when_available.html.erb
:<form
data-controller="product-notify"
data-action="ajax:success->product-notify#result"
class="product-notify-me mt-4" data-remote="true" action="<%= spree.product_notify_path %>" method="post">
<input
type="hidden"
name="product_notification[product_id]"
value="<%= @product.id %>"
/>
<div class="form-group mb-2">
<label>Notify me when in stock</label>
<input
name="product_notification[email]"
data-product-notify-target="email"
class="spree-flat-input"
type="text" placeholder="Enter your email address"
/>
</div>
<span class="product-description">Your email address will only be used for this notification, after which it gets deleted.</span>
<div>
<button class="btn btn-primary w-100 text-uppercase font-weight-bold mt-2">Notify me</button>
</div>
<div data-product-notify-target="display">
</div>
</form>
지금까지, 나는 rails 폼 요소를 사용하는 방식을 바꾸지 않았지만, 당신은 반드시 이렇게 해야 합니다.나는 이곳에서 자극을 사용하는데, 너는 정말 필요 없다.나는 단지 위의 컨트롤러에 aax 요청을 해서 product_id
와 email
를 전송하고, 오류가 발생했을 때 UI를 업데이트할 뿐이다.내부
views/spree/products/notify/notify_me.html.erb
:<%# This is server-rendered %>
<% if @notif_saved %>
<div class="alert alert-success">
Great! We'll send you a one-time email when item becomes available.
</div>
<% else %>
<div class="alert alert-danger">
Oops! You may have provided an invalid email address.
</div>
<% end %>
자극 제어기:
import { Controller } from "stimulus"
export default class extends Controller {
static targets = [ "display", "email" ]
result(event) {
const data = event.detail[0].body.innerHTML
if (data.length > 0) {
this.emailTarget.value = ""
return this.displayTarget.innerHTML = data
}
}
}
간단한 자바스크립트로 원하는 것을 실현할 수 있기 때문에 자극을 사용하는 것은 지나치다.자극을 사용하려면 views/spree/shared/_head.html.erb
에서 js 파일을 가져와야 합니다이 단계에서는 전자 메일 주소를 저장할 때 다음을 볼 수 있습니다.
notifees 계수 보이기
제품의 총 잠재 고객 수를 확인하려면
views/spree/admin/products/index.html.erb
, 루프 내, 표에 다음을 추가합니다. <td class="notify"><%= product.product_notifications.count %></td>
실수로 메일을 보냈어요.
"backordable"에 확인 작업을 추가하길 원할 수도 있습니다. 언제든지 선택/취소를 하면 이메일을 보낼 수 있습니다😁
큰 문제
이 실현에는 결함이 하나 있다."인벤토리 추적"을 선택/선택 취소하면 작업이 Spree::Admin::VariantsIncludingMasterController#update, 가리키기here에 있기 때문에 트리거되지 않습니다.
결론
나는 여전히 Spree Commerce의 기능을 탐색하고 있다.나는 이 실현이 결코 완벽하지 않다고 생각하지만, 나에게는 이것이 출발점이다.더 좋은 방법을 찾겠지만, Rails 이벤트 경로에 가서 데이터베이스 업데이트를 보고 싶지 않습니다.만약 더 좋은 해결 방안이 있다면 저에게 알려 주세요.현재, 나는 이러한 방법을 사용하여 코드를 변경하여 고객이 제품 id가 아닌 변형 id를 구독할 수 있도록 할 것이다.
편집자
한 번 써서 여기저기 쓰다.우리는
VariantsIncludingMasterController
의 or 논리가 필요하기 때문에 코드를 StockItemsControllerDecorator
에서 조수 방법으로 옮깁니다.module NotifyCustomersHelper
# We've made the executive decision by not keeping stocks.
# Alert all customers that the product is available to purchase.
def notify_notifiees
variant_id = stock_item.variant.id
email_all_notifiees(variant_id)
end
def process_notifiees_on_stock_movement
quantity = params[:stock_movement][:quantity].to_i
variant_id = params[:variant_id]
if quantity > 0
email_all_notifiees(variant_id)
end
end
def email_all_notifiees(variant_id)
product_id = Spree::Variant.find(variant_id).product.id
notifiees = lookup_notifiees_by(product_id)
send_notification_email(notifiees)
# We said we'd delete their email address
notifiees.destroy_all
end
def process_notifiees_on_stock_item
# Backorderable: boolean
# stock_item.backorderable
# Number of items in stock: integer
# stock_item.count_on_hand
if stock_item.count_on_hand > 0
variant_id = stock_item.variant.id
email_all_notifiees(variant_id)
end
end
def lookup_notifiees_by(product_id)
ProductNotification.where(product_id: product_id)
end
def send_notification_email(notifiees)
if notifiees.present?
emails_to_send = notifiees.pluck(:email)
# send the email
end
end
end
이제 우리StockItemsControllerDecorator
는:# see https://github.com/spree/spree/blob/master/backend/app/controllers/spree/admin/stock_items_controller.rb
module Spree
module Admin
module StockItemsControllerDecorator
include NotifyCustomersHelper
def self.prepended(base)
base.before_action :process_notifiees_on_stock_item, only: :update
# We have not taken into account should stock_movement.save fails.
# see https://github.com/spree/spree/blob/master/backend/app/controllers/spree/admin/stock_items_controller.rb#L13
base.before_action :process_notifiees_on_stock_movement, only: :create
base.before_action :notify_notifiees, only: :destroy
end
end
end
end
::Spree::Admin::StockItemsController.prepend Spree::Admin::StockItemsControllerDecorator if ::Spree::Admin::StockItemsController.included_modules.exclude?(Spree::Admin::StockItemsControllerDecorator)
다음에 VariantsIncludingMasterControllerDecorator
내부에 spree/admin/variants_including_master_controller_decorator.rb
:# See: https://github.com/spree/spree/blob/master/backend/app/controllers/spree/admin/variants_including_master_controller.rb
module Spree
module Admin
module VariantsIncludingMasterControllerDecorator
include NotifyCustomersHelper
def self.prepended(base)
base.before_action :send_notification_email_on_inventory_change, only: :update
end
def send_notification_email_on_inventory_change
variant_id = params[:id].to_i
track_inventory = params[:variant][:track_inventory]
# If we're no longer tracking, send email
# track_inventory comes in the form of string "true" or "false"
if track_inventory == 'false'
email_all_notifiees(variant_id)
end
end
end
end
end
::Spree::Admin::VariantsIncludingMasterController.prepend Spree::Admin::VariantsIncludingMasterControllerDecorator if ::Spree::Admin::VariantsIncludingMasterController.included_modules.exclude?(Spree::Admin::VariantsIncludingMasterControllerDecorator)
이제 재고를 추적하지 않으면 모든 고객이 이메일 통지를 받게 됩니다.이런 방법에 주의해라."이 확인란의 선택을 실수로 취소하여 모든""관찰가능""고객에게 이메일을 보낼 수 있습니다."이 조작을 위한 전용 단추를 만들어야 할 수도 있습니다.숙제
고객이 보고 있는 제품을
send_notification_email
기능에 전달해야 합니다.이메일에서 고객은 링크를 클릭하여 제품 페이지로 바로 이동합니다.
Reference
이 문제에 관하여(고객이 Spree Commerce를 통해 품절 제품 구독 가능), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mirmayne/let-your-customers-subscribe-to-an-out-of-stock-product-with-spree-commerce-2mgl텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)