Add CustomerAccountTransactions::DataLoaderService

It's used to load customer transactions related to a user and a specific
enterprise
This commit is contained in:
Gaetan Craig-Riou
2026-01-21 16:24:38 +11:00
parent 1b468522e6
commit e21fadd124
4 changed files with 106 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ class Customer < ApplicationRecord
belongs_to :enterprise
belongs_to :user, class_name: "Spree::User", optional: true
has_many :orders, class_name: "Spree::Order", dependent: :nullify
has_many :customer_account_transactions, dependent: :restrict_with_error
before_validation :downcase_email
before_validation :empty_code
before_create :associate_user

View File

@@ -0,0 +1,28 @@
# frozen_string_literal: false
module CustomerAccountTransactions
class DataLoaderService
attr_reader :user, :enterprise
def initialize(user:, enterprise:)
@user = user
@enterprise = enterprise
end
def customer_account_transactions
return [] if user.customers.empty?
enterprise_customer = user.customers.find_by(enterprise: )
return [] if enterprise_customer.nil?
enterprise_customer.customer_account_transactions.order(id: :desc)
end
def available_credit
return 0 if customer_account_transactions.empty?
# We are ordered by newest, so the lastest transaction is the first one
customer_account_transactions.first.balance
end
end
end

View File

@@ -5,6 +5,7 @@ RSpec.describe Customer do
it { is_expected.to belong_to(:user).optional }
it { is_expected.to belong_to(:bill_address).optional }
it { is_expected.to belong_to(:ship_address).optional }
it { is_expected.to have_many(:customer_account_transactions) }
describe 'an existing customer' do
let(:customer) { create(:customer) }

View File

@@ -0,0 +1,76 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe CustomerAccountTransactions::DataLoaderService do
subject { described_class.new(user:, enterprise:) }
let!(:payment_method) {
create(
:payment_method,
name: CustomerAccountTransaction::DEFAULT_PAYMENT_METHOD_NAME,
distributors: [enterprise]
)
}
let(:user) { create(:user) }
let(:enterprise) { create(:distributor_enterprise) }
describe "#customer_account_transactions" do
it "returns a list of customer payments ordered by newest" do
customer = create(:customer, email: user.email, enterprise:)
user.customers << customer
customer_account_transactions = create_list(:customer_account_transaction, 3, customer:)
# This initial transaction created automatically by CustomerAccountTransaction
first_transaction = CustomerAccountTransaction.where(customer: customer).first
expect(subject.customer_account_transactions).to eq([
customer_account_transactions.third,
customer_account_transactions.second,
customer_account_transactions.first,
first_transaction
])
end
context "with no customer associated with the user" do
it "returns an empty array" do
expect(subject.customer_account_transactions).to eq([])
end
end
context "with no customer associated with the given enterprise" do
it "returns an empty array" do
customer = create(:customer, email: user.email)
user.customers << customer
expect(subject.customer_account_transactions).to eq([])
end
end
end
describe "#available_credit" do
it "returns the total credit availble to the user" do
customer = create(:customer, email: user.email, enterprise:)
user.customers << customer
create(:customer_account_transaction, customer:, amount: 10.00)
create(:customer_account_transaction, customer:, amount: -2.00)
create(:customer_account_transaction, customer:, amount: 5.00)
expect(subject.available_credit).to eq(13.00)
end
context "with no customer associated with the user" do
it "returns 0" do
expect(subject.available_credit).to eq(0)
end
end
context "with no customer associated with the given enterprise" do
it "returns 0" do
customer = create(:customer, email: user.email)
user.customers << customer
expect(subject.available_credit).to eq(0)
end
end
end
end