Skip to content

Commit

Permalink
close #2112 create job when add to cart
Browse files Browse the repository at this point in the history
  • Loading branch information
panhachom committed Dec 11, 2024
1 parent 2f1ad7f commit 7251000
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 0 deletions.
56 changes: 56 additions & 0 deletions app/controllers/spree/api/v2/storefront/enqueue_cart_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module Spree
module Api
module V2
module Storefront
class EnqueueCartController < CartController
# override
def add_item
spree_authorize! :update, spree_current_order, order_token
spree_authorize! :show, @variant

job = SpreeCmCommissioner::EnqueueCart::AddItemJob.perform_later(
spree_current_order.id,
@variant.id,
add_item_params[:quantity],
add_item_params[:public_metadata],
add_item_params[:private_metadata],
add_item_params[:options]
)

result = SpreeCmCommissioner::EnqueueCart::AddItemStatusMarker.call(
order_number: spree_current_order.number,
job_id: job.job_id,
status: 'processing',
queued_at: Time.current,
variant_id: @variant.id,
quantity: add_item_params[:quantity]
)

struct = Struct.new(:id, :status, :queued_at, :collection_reference, :document_reference)

render_serialized_payload do
serialize_resource(
struct.new(
job.job_id,
result.firestore_status,
result.firestore_queued_at,
result.firestore_collection_reference,
result.firestore_document_reference
)
)
end
end

def id
SecureRandom.hex
end

# override
def resource_serializer
Spree::V2::Storefront::FirestoreQueueSerializer
end
end
end
end
end
end
43 changes: 43 additions & 0 deletions app/interactors/spree_cm_commissioner/enqueue_cart/add_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module SpreeCmCommissioner
module EnqueueCart
class AddItem < BaseInteractor
delegate :order_id, :variant_id, :job_id, :quantity, :public_metadata, :private_metadata, :options, to: :context

def call
result = add_item_to_cart
if result.success?
update_status('completed')
else
update_status('failed')
end
end

def add_item_to_cart
Spree::Cart::AddItem.call(
order: order,
variant: variant,
quantity: quantity,
public_metadata: public_metadata,
private_metadata: private_metadata,
options: options
)
end

def update_status(status)
SpreeCmCommissioner::EnqueueCart::AddItemStatusMarker.call(
order_number: order.number,
job_id: job_id,
status: status
)
end

def order
@order ||= Spree::Order.find(order_id)
end

def variant
@variant ||= Spree::Variant.find(variant_id)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require 'google/cloud/firestore'

module SpreeCmCommissioner
module EnqueueCart
class AddItemStatusMarker < BaseInteractor
delegate :order_number, :job_id, :status, :queued_at, :variant_id, :quantity, to: :context

def call
if order_number.nil? || job_id.nil? || status.nil?
context.fail!(message: 'Missing required fields')
return
end
update_cart_firestore_status

assign_firestore_context_attributes
end

def firestore
@firestore ||= Google::Cloud::Firestore.new(project_id: service_account[:project_id], credentials: service_account)
end

def service_account
@service_account ||= Rails.application.credentials.cloud_firestore_service_account
end

def update_cart_firestore_status
data_to_set = build_data_to_set

firestore.col('queues')
.doc('cart')
.col(order_number)
.doc(job_id)
.set(data_to_set, merge: true)
end

def build_data_to_set
{
status: status,
queued_at: queued_at.presence,
variant_id: variant_id.presence,
quantity: quantity.presence
}.compact
end

def firestore_object
firestore.col('queues').doc('cart').col(order_number).doc(job_id).get
end

def firestore_status
firestore_object[:status]
end

def firestore_queued_at
firestore_object[:queued_at]
end

def firestore_collection_reference
firestore_object.ref.path
end

def firestore_document_reference
firestore_collection_reference.split('/documents').last
end

def assign_firestore_context_attributes
document = firestore_object

context.firestore_status = document[:status]
context.firestore_queued_at = document[:queued_at]
context.firestore_collection_reference = document.ref.path
context.firestore_document_reference = document.ref.path.split('/documents').last
end
end
end
end
17 changes: 17 additions & 0 deletions app/jobs/spree_cm_commissioner/enqueue_cart/add_item_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module SpreeCmCommissioner
module EnqueueCart
class AddItemJob < ApplicationJob
def perform(order_id, variant_id, quantity, public_metadata, private_metadata, options) # rubocop:disable Metrics/ParameterLists
SpreeCmCommissioner::EnqueueCart::AddItem.call(
order_id: order_id,
variant_id: variant_id,
quantity: quantity,
public_metadata: public_metadata,
private_metadata: private_metadata,
options: options,
job_id: job_id
)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Spree
module V2
module Storefront
class FirestoreQueueSerializer < BaseSerializer
attributes :status, :queued_at, :collection_reference, :document_reference
end
end
end
end
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,9 @@
patch :restart_checkout_flow
end

resource :enqueue_cart, controller: :enqueue_cart do
post :add_item
end
resources :wished_items
resources :user_promotion
resources :order_promotions
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'spec_helper'

RSpec.describe SpreeCmCommissioner::EnqueueCart::AddItemStatusMarker do
let(:order_number) { 'R12345678' }
let(:job_id) { 'job_456' }
let(:status) { 'processing' }
let(:queued_at) { Time.now }

subject { described_class.new(order_number: order_number, job_id: job_id, status: status, queued_at: queued_at) }

describe '#call' do
it 'fails when order_number is missing' do
allow(subject).to receive(:order_number).and_return(nil)
expect { subject.call }.to raise_error(Interactor::Failure)
end

it 'fails when job_id is missing' do
allow(subject).to receive(:job_id).and_return(nil)
expect { subject.call }.to raise_error(Interactor::Failure)
end

it 'fails when status is missing' do
allow(subject).to receive(:status).and_return(nil)
expect { subject.call }.to raise_error(Interactor::Failure)
end
end
end
34 changes: 34 additions & 0 deletions spec/jobs/spree_cm_commissioner/add_item_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'spec_helper'

RSpec.describe SpreeCmCommissioner::EnqueueCart::AddItemJob, type: :job do
describe '#perform' do
let(:order_id) { 1 }
let(:variant_id) { 2 }
let(:quantity) { 2 }
let(:public_metadata) { { data: 'data' } }
let(:private_metadata) { { data: 'info' } }
let(:options) { { key: 'value' } }

it 'calls SpreeCmCommissioner::EnqueueCart::AddItem with correct arguments' do
add_item = class_double("SpreeCmCommissioner::EnqueueCart::AddItem")
allow(add_item).to receive(:call).and_return(true)

stub_const("SpreeCmCommissioner::EnqueueCart::AddItem", add_item)

job = described_class.new
allow(job).to receive(:job_id).and_return('test-job-id')

job.perform(order_id, variant_id, quantity, public_metadata, private_metadata, options)

expect(add_item).to have_received(:call).with(
order_id: order_id,
variant_id: variant_id,
quantity: quantity,
public_metadata: public_metadata,
private_metadata: private_metadata,
options: options,
job_id: 'test-job-id'
)
end
end
end

0 comments on commit 7251000

Please sign in to comment.