Extract balance-specific serializer

So we only show the customer balance where really needed. Aggregating
the balance can be costly. Also, we avoid defensive coding.
This commit is contained in:
Pau Perez
2020-11-24 17:38:21 +01:00
parent 9d0dd968b1
commit 96a91969c9
6 changed files with 113 additions and 34 deletions

View File

@@ -17,9 +17,10 @@ module Admin
respond_to do |format|
format.html
format.json do
render_as_json @collection,
tag_rule_mapping: tag_rule_mapping,
customer_tags: customer_tags_by_id
render json: @collection,
each_serializer: ::Api::Admin::CustomerWithBalanceSerializer,
tag_rule_mapping: tag_rule_mapping,
customer_tags: customer_tags_by_id
end
end
end
@@ -63,9 +64,11 @@ module Admin
private
def collection
return Customer.where("1=0") unless json_request? && params[:enterprise_id].present?
CustomersWithBalance.new(managed_enterprise_id).query
if json_request? && params[:enterprise_id].present?
CustomersWithBalance.new(managed_enterprise_id).query
else
Customer.where('1=0')
end
end
def managed_enterprise_id

View File

@@ -4,13 +4,11 @@ module Api
module Admin
class CustomerSerializer < ActiveModel::Serializer
attributes :id, :email, :enterprise_id, :user_id, :code, :tags, :tag_list, :name,
:allow_charges, :default_card_present?, :balance, :balance_status
:allow_charges, :default_card_present?
has_one :ship_address, serializer: Api::AddressSerializer
has_one :bill_address, serializer: Api::AddressSerializer
delegate :balance_value, to: :object
def name
object.name.presence || object.bill_address.andand.full_name
end
@@ -19,20 +17,6 @@ module Api
customer_tag_list.join(",")
end
def balance
Spree::Money.new(balance_value, currency: Spree::Config[:currency]).to_s
end
def balance_status
if balance_value.positive?
"credit_owed"
elsif balance_value.negative?
"balance_due"
else
""
end
end
def tags
customer_tag_list.map do |tag|
tag_rule_map = options[:tag_rule_mapping].andand[tag]

View File

@@ -0,0 +1,25 @@
# frozen_string_literal: true
module Api
module Admin
class CustomerWithBalanceSerializer < CustomerSerializer
attributes :balance, :balance_status
delegate :balance_value, to: :object
def balance
Spree::Money.new(balance_value, currency: Spree::Config[:currency]).to_s
end
def balance_status
if balance_value.positive?
"credit_owed"
elsif balance_value.negative?
"balance_due"
else
""
end
end
end
end
end

View File

@@ -41,6 +41,11 @@ module Admin
expect(ActiveModel::ArraySerializer).to receive(:new)
spree_get :index, params
end
it 'includes the customer balance in the response' do
spree_get :index, params
expect(json_response.first["balance"]).to eq("$0.00")
end
end
context "and enterprise_id is not given in params" do

View File

@@ -97,9 +97,33 @@ feature 'Customers' do
describe "for a shop with multiple customers" do
before do
build_balance(customer1, managed_distributor1, 88)
build_balance(customer2, managed_distributor1, -99)
build_balance(customer4, managed_distributor1, 0)
create(
:order,
total: 0,
payment_total: 88,
distributor: managed_distributor1,
user: nil,
completed_at: Time.zone.now,
customer: customer1
)
create(
:order,
total: 99,
payment_total: 0,
distributor: managed_distributor1,
user: nil,
completed_at: Time.zone.now,
customer: customer2
)
create(
:order,
total: 0,
payment_total: 0,
distributor: managed_distributor1,
user: nil,
completed_at: Time.zone.now,
customer: customer4
)
customer4.update enterprise: managed_distributor1
end
@@ -121,14 +145,6 @@ feature 'Customers' do
expect(page).to have_content "$0.00"
end
end
def build_balance(customer, enterprise, balance)
order = build(:order, total: balance, payment_total: 0, distributor: enterprise)
order.email = customer.email
order.customer_id = customer.id
order.completed_at = Time.zone.now
order.save!
end
end
it "allows updating of attributes" do

View File

@@ -0,0 +1,46 @@
# frozen_string_literal: true
require 'spec_helper'
describe Api::Admin::CustomerWithBalanceSerializer do
let(:serialized_customer) { described_class.new(customer) }
describe '#balance' do
let(:customer) { double(Customer, balance_value: 1.2) }
let(:money) { instance_double(Spree::Money, to_s: "$1.20") }
before do
allow(Spree::Money).to receive(:new).with(1.2, currency: "AUD") { money }
end
it 'returns the balance_value as a money amount' do
expect(serialized_customer.balance).to eq("$1.20")
end
end
describe '#balance_status' do
context 'when the balance_value is positive' do
let(:customer) { double(Customer, balance_value: 1) }
it 'returns credit_owed' do
expect(serialized_customer.balance_status).to eq("credit_owed")
end
end
context 'when the balance_value is negative' do
let(:customer) { double(Customer, balance_value: -1) }
it 'returns credit_owed' do
expect(serialized_customer.balance_status).to eq("balance_due")
end
end
context 'when the balance_value is zero' do
let(:customer) { double(Customer, balance_value: 0) }
it 'returns credit_owed' do
expect(serialized_customer.balance_status).to eq("")
end
end
end
end