Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

close #2112 enqueue add to cart #2113

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module Spree
module Api
module V2
module Storefront
module QueueCart
class LineItemsController < CartController
before_action :ensure_order, only: :create
before_action :load_variant, only: :create
before_action :ensure_cart_exist, only: :create

# override
def create
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]
)

line_item_queue = SpreeCmCommissioner::QueueItem.new(
id: job.job_id,
status: result.firestore_status,
queued_at: result.firestore_queued_at,
collection_reference: result.firestore_collection_reference,
document_reference: result.firestore_document_reference
)

render_serialized_payload do
serialize_resource(line_item_queue)
end
end

# override
def resource_serializer
Spree::V2::Storefront::FirestoreQueueSerializer
end
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
13 changes: 13 additions & 0 deletions app/serializables/spree_cm_commissioner/queue_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module SpreeCmCommissioner
class QueueItem
attr_accessor :id, :status, :queued_at, :collection_reference, :document_reference

def initialize(id:, status:, queued_at:, collection_reference:, document_reference:)
@id = id
@status = status
@queued_at = queued_at
@collection_reference = collection_reference
@document_reference = document_reference
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
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@
patch :restart_checkout_flow
end

namespace :queue_cart do
resources :line_items, only: [:create]
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
Loading