Add incoming boolean field to Exchange, determine exchange direction from this field rather than sender/receiver roles

This commit is contained in:
Rohan Mitchell
2014-03-26 11:19:35 +11:00
parent 57ca48dc4a
commit ac92d0919a
6 changed files with 97 additions and 41 deletions

View File

@@ -15,10 +15,11 @@ class Exchange < ActiveRecord::Base
accepts_nested_attributes_for :variants
scope :incoming, joins(:order_cycle).where('exchanges.receiver_id = order_cycles.coordinator_id')
scope :outgoing, joins(:order_cycle).where('exchanges.sender_id = order_cycles.coordinator_id')
scope :incoming, where(incoming: true)
scope :outgoing, where(incoming: false)
scope :from_enterprises, lambda { |enterprises| where('exchanges.sender_id IN (?)', enterprises) }
scope :to_enterprises, lambda { |enterprises| where('exchanges.receiver_id IN (?)', enterprises) }
scope :supplying_to, lambda { |distributor| where('exchanges.incoming OR exchanges.receiver_id = ?', distributor) }
scope :with_variant, lambda { |variant| joins(:exchange_variants).where('exchange_variants.variant_id = ?', variant) }
scope :with_any_variant, lambda { |variants| joins(:exchange_variants).where('exchange_variants.variant_id IN (?)', variants).select('DISTINCT exchanges.*') }
scope :with_product, lambda { |product| joins(:exchange_variants).where('exchange_variants.variant_id IN (?)', product.variants_including_master) }
@@ -32,10 +33,6 @@ class Exchange < ActiveRecord::Base
exchange
end
def incoming?
receiver == order_cycle.coordinator
end
def role
incoming? ? 'supplier' : 'distributor'
end

View File

@@ -78,11 +78,11 @@ class OrderCycle < ActiveRecord::Base
end
def suppliers
self.exchanges.where(:receiver_id => self.coordinator).map(&:sender).uniq
self.exchanges.incoming.map(&:sender).uniq
end
def distributors
self.exchanges.where(:sender_id => self.coordinator).map(&:receiver).uniq
self.exchanges.outgoing.map(&:receiver).uniq
end
def variants
@@ -90,7 +90,7 @@ class OrderCycle < ActiveRecord::Base
end
def distributed_variants
self.exchanges.where(:sender_id => self.coordinator).map(&:variants).flatten.uniq
self.exchanges.outgoing.map(&:variants).flatten.uniq
end
def variants_distributed_by(distributor)
@@ -239,11 +239,10 @@ class OrderCycle < ActiveRecord::Base
end
def exchanges_carrying(variant, distributor)
exchanges.to_enterprises([coordinator, distributor]).with_variant(variant)
exchanges.supplying_to(distributor).with_variant(variant)
end
def exchanges_supplying(order)
variants = order.line_items.map(&:variant)
exchanges.to_enterprises([coordinator, order.distributor]).with_any_variant(variants)
exchanges.supplying_to(order.distributor).with_any_variant(order.variants)
end
end

View File

@@ -0,0 +1,25 @@
class AddIncomingToExchanges < ActiveRecord::Migration
class Exchange < ActiveRecord::Base
belongs_to :order_cycle
belongs_to :receiver, :class_name => 'Enterprise'
def incoming?
receiver == order_cycle.coordinator
end
end
def up
add_column :exchanges, :incoming, :boolean, null: false, default: false
# Initialise based on whether the exchange is going to or coming
# from the order cycle coordinator
Exchange.all.each do |exchange|
exchange.update_attribute :incoming, exchange.incoming?
end
end
def down
remove_column :exchanges, :incoming
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140213003443) do
ActiveRecord::Schema.define(:version => 20140324025840) do
create_table "adjustment_metadata", :force => true do |t|
t.integer "adjustment_id"
@@ -236,8 +236,9 @@ ActiveRecord::Schema.define(:version => 20140213003443) do
t.integer "payment_enterprise_id"
t.string "pickup_time"
t.string "pickup_instructions"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "incoming", :default => false, :null => false
end
create_table "landing_page_images", :force => true do |t|

View File

@@ -49,9 +49,8 @@ describe Exchange do
let(:coordinator) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
let(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator }
let(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor }
let(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator, incoming: true }
let(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor, incoming: false }
it "returns true for incoming exchanges" do
incoming_exchange.should be_incoming
@@ -78,29 +77,62 @@ describe Exchange do
describe "scopes" do
let(:supplier) { create(:supplier_enterprise) }
let(:coordinator) { create(:distributor_enterprise) }
let(:coordinator) { create(:distributor_enterprise, is_primary_producer: true) }
let(:distributor) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
let!(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator }
let!(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor }
describe "finding exchanges by direction" do
let!(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator, incoming: true }
let!(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor, incoming: false }
it "finds incoming exchanges" do
Exchange.incoming.should == [incoming_exchange]
it "finds incoming exchanges" do
Exchange.incoming.should == [incoming_exchange]
end
it "finds outgoing exchanges" do
Exchange.outgoing.should == [outgoing_exchange]
end
it "correctly determines direction of exchanges between the same enterprise" do
incoming_exchange.update_attributes sender: coordinator, incoming: true
outgoing_exchange.update_attributes receiver: coordinator, incoming: false
Exchange.incoming.should == [incoming_exchange]
Exchange.outgoing.should == [outgoing_exchange]
end
it "finds exchanges going to any of a number of enterprises" do
Exchange.to_enterprises([coordinator]).should == [incoming_exchange]
Exchange.to_enterprises([coordinator, distributor]).sort.should == [incoming_exchange, outgoing_exchange].sort
end
it "finds exchanges coming from any of a number of enterprises" do
Exchange.from_enterprises([coordinator]).should == [outgoing_exchange]
Exchange.from_enterprises([supplier, coordinator]).sort.should == [incoming_exchange, outgoing_exchange].sort
end
end
it "finds outgoing exchanges" do
Exchange.outgoing.should == [outgoing_exchange]
end
describe "finding exchanges supplying to a distributor" do
it "returns incoming exchanges" do
d = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, incoming: true)
it "finds exchanges going to any of a number of enterprises" do
Exchange.to_enterprises([coordinator]).should == [incoming_exchange]
Exchange.to_enterprises([coordinator, distributor]).sort.should == [incoming_exchange, outgoing_exchange].sort
end
oc.exchanges.supplying_to(d).should == [ex]
end
it "finds exchanges coming from any of a number of enterprises" do
Exchange.from_enterprises([coordinator]).should == [outgoing_exchange]
Exchange.from_enterprises([supplier, coordinator]).sort.should == [incoming_exchange, outgoing_exchange].sort
it "returns outgoing exchanges to the distributor" do
d = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, receiver: d, incoming: false)
oc.exchanges.supplying_to(d).should == [ex]
end
it "does not return outgoing exchanges to a different distributor" do
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, receiver: d1, incoming: false)
oc.exchanges.supplying_to(d2).should be_empty
end
end
it "finds exchanges with a particular variant" do
@@ -167,6 +199,7 @@ describe Exchange do
exchange.to_h.should ==
{'id' => exchange.id, 'order_cycle_id' => oc.id,
'sender_id' => exchange.sender_id, 'receiver_id' => exchange.receiver_id,
'incoming' => exchange.incoming,
'payment_enterprise_id' => exchange.payment_enterprise_id, 'variant_ids' => exchange.variant_ids.sort,
'enterprise_fee_ids' => exchange.enterprise_fee_ids.sort,
'pickup_time' => exchange.pickup_time, 'pickup_instructions' => exchange.pickup_instructions,
@@ -176,6 +209,7 @@ describe Exchange do
it "converts to a hash of core attributes only" do
exchange.to_h(true).should ==
{'sender_id' => exchange.sender_id, 'receiver_id' => exchange.receiver_id,
'incoming' => exchange.incoming,
'payment_enterprise_id' => exchange.payment_enterprise_id, 'variant_ids' => exchange.variant_ids.sort,
'enterprise_fee_ids' => exchange.enterprise_fee_ids.sort,
'pickup_time' => exchange.pickup_time, 'pickup_instructions' => exchange.pickup_instructions}

View File

@@ -82,7 +82,7 @@ describe OrderCycle do
p = create(:product)
s = create(:supplier_enterprise)
oc = create(:simple_order_cycle)
ex = create(:exchange, order_cycle: oc, sender: s, receiver: oc.coordinator)
ex = create(:exchange, order_cycle: oc, sender: s, receiver: oc.coordinator, incoming: true)
ex.variants << p.master
p.reload
@@ -137,9 +137,9 @@ describe OrderCycle do
it "reports its suppliers" do
oc = create(:simple_order_cycle)
e1 = create(:exchange,
e1 = create(:exchange, incoming: true,
order_cycle: oc, receiver: oc.coordinator, sender: create(:enterprise))
e2 = create(:exchange,
e2 = create(:exchange, incoming: true,
order_cycle: oc, receiver: oc.coordinator, sender: create(:enterprise))
oc.suppliers.sort.should == [e1.sender, e2.sender].sort
@@ -148,9 +148,9 @@ describe OrderCycle do
it "reports its distributors" do
oc = create(:simple_order_cycle)
e1 = create(:exchange,
e1 = create(:exchange, incoming: false,
order_cycle: oc, sender: oc.coordinator, receiver: create(:enterprise))
e2 = create(:exchange,
e2 = create(:exchange, incoming: false,
order_cycle: oc, sender: oc.coordinator, receiver: create(:enterprise))
oc.distributors.sort.should == [e1.receiver, e2.receiver].sort
@@ -182,11 +182,11 @@ describe OrderCycle do
@d1 = create(:enterprise)
@d2 = create(:enterprise)
@e0 = create(:exchange,
@e0 = create(:exchange, incoming: true,
order_cycle: @oc, sender: create(:enterprise), receiver: @oc.coordinator)
@e1 = create(:exchange,
@e1 = create(:exchange, incoming: false,
order_cycle: @oc, sender: @oc.coordinator, receiver: @d1)
@e2 = create(:exchange,
@e2 = create(:exchange, incoming: false,
order_cycle: @oc, sender: @oc.coordinator, receiver: @d2)
@p0 = create(:simple_product)