Skip to content

Commit 4a1a9a3

Browse files
committed
Rename Refund to Return
- better name describes the acutal feature that is returing products not refunding money - maintain backward compatibtility by transforming deprecated events classes and payloads
1 parent 1edd07a commit 4a1a9a3

File tree

12 files changed

+424
-14
lines changed

12 files changed

+424
-14
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Ordering
2+
class AddItemToReturn < Infra::Command
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
attribute :product_id, Infra::Types::UUID
6+
7+
alias aggregate_id return_id
8+
end
9+
10+
AddItemToRefund = AddItemToReturn
11+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module Ordering
2+
class CreateDraftReturn < Infra::Command
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
6+
alias aggregate_id return_id
7+
end
8+
9+
CreateDraftRefund = CreateDraftReturn
10+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Ordering
2+
class RemoveItemFromReturn < Infra::Command
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
attribute :product_id, Infra::Types::UUID
6+
7+
alias aggregate_id return_id
8+
end
9+
10+
RemoveItemFromRefund = RemoveItemFromReturn
11+
end
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Ordering
2+
class DraftReturnCreated < Infra::Event
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
attribute :returnable_products, Infra::Types::Array.of(
6+
Infra::Types::Hash.schema(
7+
product_id: Infra::Types::UUID,
8+
quantity: Infra::Types::Integer
9+
)
10+
)
11+
end
12+
13+
DraftRefundCreated = DraftReturnCreated
14+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Ordering
2+
class ItemAddedToReturn < Infra::Event
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
attribute :product_id, Infra::Types::UUID
6+
end
7+
8+
ItemAddedToRefund = ItemAddedToReturn
9+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Ordering
2+
class ItemRemovedFromReturn < Infra::Event
3+
attribute :return_id, Infra::Types::UUID
4+
attribute :order_id, Infra::Types::UUID
5+
attribute :product_id, Infra::Types::UUID
6+
end
7+
8+
ItemRemovedFromRefund = ItemRemovedFromReturn
9+
end
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
module Ordering
2+
class Return
3+
include AggregateRoot
4+
5+
ExceedsOrderQuantityError = Class.new(StandardError)
6+
ReturnHaveNotBeenRequestedForThisProductError = Class.new(StandardError)
7+
8+
def initialize(id)
9+
@id = id
10+
@return_items = ItemsList.new
11+
end
12+
13+
def create_draft(order_id, returnable_products)
14+
apply DraftReturnCreated.new(data: { return_id: @id, order_id: order_id, returnable_products: returnable_products })
15+
end
16+
17+
def add_item(product_id)
18+
raise ExceedsOrderQuantityError unless enough_items?(product_id)
19+
apply ItemAddedToReturn.new(data: { return_id: @id, order_id: @order_id, product_id: product_id })
20+
end
21+
22+
def remove_item(product_id)
23+
raise ReturnHaveNotBeenRequestedForThisProductError unless @return_items.quantity(product_id).positive?
24+
apply ItemRemovedFromReturn.new(data: { return_id: @id, order_id: @order_id, product_id: product_id })
25+
end
26+
27+
on DraftReturnCreated do |event|
28+
@order_id = event.data[:order_id]
29+
@returnable_products = event.data[:returnable_products]
30+
end
31+
32+
on ItemAddedToReturn do |event|
33+
@return_items.increase_quantity(event.data[:product_id])
34+
end
35+
36+
on ItemRemovedFromReturn do |event|
37+
@return_items.decrease_quantity(event.data[:product_id])
38+
end
39+
40+
private
41+
42+
def enough_items?(product_id)
43+
@return_items.quantity(product_id) < returnable_quantity(product_id)
44+
end
45+
46+
def returnable_quantity(product_id)
47+
product = @returnable_products.find { |product| product.fetch(:product_id) == product_id }
48+
product.fetch(:quantity)
49+
end
50+
end
51+
52+
class ItemsList
53+
attr_reader :return_items
54+
55+
def initialize
56+
@return_items = Hash.new(0)
57+
end
58+
59+
def increase_quantity(product_id)
60+
return_items[product_id] = quantity(product_id) + 1
61+
end
62+
63+
def decrease_quantity(product_id)
64+
return_items[product_id] -= 1
65+
return_items.delete(product_id) if quantity(product_id).equal?(0)
66+
end
67+
68+
def quantity(product_id)
69+
return_items[product_id]
70+
end
71+
end
72+
73+
Refund = Return
74+
RefundableProducts = ReturnableProducts if defined?(ReturnableProducts)
75+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module Ordering
2+
class ReturnableProducts
3+
def call(event_store, order_id)
4+
accepted_event = event_store
5+
.read.backward
6+
.stream("Pricing::Offer$#{order_id}")
7+
.of_type(Pricing::OfferAccepted)
8+
.first
9+
10+
placed_event = event_store
11+
.read
12+
.stream("Fulfillment::Order$#{order_id}")
13+
.first
14+
15+
accepted_event.data.fetch(:order_lines) if placed_event
16+
end
17+
end
18+
19+
RefundableProducts = ReturnableProducts
20+
end
Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,51 @@
11
module Ordering
2-
class OnCreateDraftRefund
2+
class OnCreateDraftReturn
33
def initialize(event_store)
44
@repository = Infra::AggregateRootRepository.new(event_store)
55
@event_store = event_store
66
end
77

88
def call(command)
9-
@repository.with_aggregate(Refund, command.aggregate_id) do |refund|
10-
refund.create_draft(
9+
@repository.with_aggregate(Return, command.aggregate_id) do |return_order|
10+
return_order.create_draft(
1111
command.order_id,
12-
refundable_products(command.order_id)
12+
returnable_products(command.order_id)
1313
)
1414
end
1515
end
1616

1717
private
1818

19-
def refundable_products(order_id)
20-
RefundableProducts.new.call(@event_store, order_id)
19+
def returnable_products(order_id)
20+
ReturnableProducts.new.call(@event_store, order_id)
2121
end
2222
end
2323

24-
class OnAddItemToRefund
24+
class OnAddItemToReturn
2525
def initialize(event_store)
2626
@repository = Infra::AggregateRootRepository.new(event_store)
2727
end
2828

2929
def call(command)
30-
@repository.with_aggregate(Refund, command.aggregate_id) do |refund|
31-
refund.add_item(command.product_id)
30+
@repository.with_aggregate(Return, command.aggregate_id) do |return_order|
31+
return_order.add_item(command.product_id)
3232
end
3333
end
3434
end
3535

36-
class OnRemoveItemFromRefund
36+
class OnRemoveItemFromReturn
3737
def initialize(event_store)
3838
@repository = Infra::AggregateRootRepository.new(event_store)
3939
end
4040

4141
def call(command)
42-
@repository.with_aggregate(Refund, command.aggregate_id) do |refund|
43-
refund.remove_item(command.product_id)
42+
@repository.with_aggregate(Return, command.aggregate_id) do |return_order|
43+
return_order.remove_item(command.product_id)
4444
end
4545
end
4646
end
47+
48+
OnCreateDraftRefund = OnCreateDraftReturn
49+
OnAddItemToRefund = OnAddItemToReturn
50+
OnRemoveItemFromRefund = OnRemoveItemFromReturn
4751
end

infra/lib/infra/event_store.rb

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
module Infra
22
class EventStore < SimpleDelegator
33
def self.main
4-
new(RailsEventStore::JSONClient.new)
4+
require_relative "../../../rails_application/lib/transformations/refund_to_return_event_mapper" rescue nil
5+
6+
if defined?(Transformations::RefundToReturnEventMapper)
7+
mapper = RubyEventStore::Mappers::PipelineMapper.new(
8+
RubyEventStore::Mappers::Pipeline.new(
9+
Transformations::RefundToReturnEventMapper.new(
10+
'Ordering::DraftRefundCreated' => 'Ordering::DraftReturnCreated',
11+
'Ordering::ItemAddedToRefund' => 'Ordering::ItemAddedToReturn',
12+
'Ordering::ItemRemovedFromRefund' => 'Ordering::ItemRemovedFromReturn'
13+
),
14+
RubyEventStore::Mappers::Transformation::DomainEvent.new,
15+
RubyEventStore::Mappers::Transformation::SymbolizeMetadataKeys.new,
16+
RubyEventStore::Mappers::Transformation::PreserveTypes.new
17+
)
18+
)
19+
else
20+
mapper = default_mapper
21+
end
22+
23+
new(RailsEventStore::JSONClient.new(mapper: mapper))
524
end
625

726
def self.in_memory
@@ -13,9 +32,26 @@ def self.in_memory
1332
end
1433

1534
def self.in_memory_rails
35+
if defined?(Transformations::RefundToReturnEventMapper)
36+
mapper = RubyEventStore::Mappers::PipelineMapper.new(
37+
RubyEventStore::Mappers::Pipeline.new(
38+
Transformations::RefundToReturnEventMapper.new(
39+
'Ordering::DraftRefundCreated' => 'Ordering::DraftReturnCreated',
40+
'Ordering::ItemAddedToRefund' => 'Ordering::ItemAddedToReturn',
41+
'Ordering::ItemRemovedFromRefund' => 'Ordering::ItemRemovedFromReturn'
42+
),
43+
RubyEventStore::Mappers::Transformation::DomainEvent.new,
44+
RubyEventStore::Mappers::Transformation::SymbolizeMetadataKeys.new
45+
)
46+
)
47+
else
48+
mapper = default_mapper
49+
end
50+
1651
new(
1752
RailsEventStore::Client.new(
18-
repository: RubyEventStore::InMemoryRepository.new
53+
repository: RubyEventStore::InMemoryRepository.new,
54+
mapper: mapper
1955
)
2056
)
2157
end
@@ -31,5 +67,16 @@ def link_event_to_stream(event, stream, expected_version: :any)
3167
expected_version: expected_version
3268
)
3369
end
70+
71+
private
72+
73+
def self.default_mapper
74+
RubyEventStore::Mappers::PipelineMapper.new(
75+
RubyEventStore::Mappers::Pipeline.new(
76+
RubyEventStore::Mappers::Transformation::DomainEvent.new,
77+
RubyEventStore::Mappers::Transformation::SymbolizeMetadataKeys.new
78+
)
79+
)
80+
end
3481
end
3582
end

0 commit comments

Comments
 (0)