auction_fun_core 0.8.5 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +2 -0
- data/CHANGELOG.md +48 -0
- data/Procfile +1 -0
- data/README.md +34 -32
- data/Rakefile +1 -1
- data/auction_fun_core.gemspec +1 -0
- data/db/migrate/20240229143000_create_auctions.rb +1 -0
- data/db/seeds.rb +87 -36
- data/i18n/en-US/contracts/contracts.en-US.yml +12 -0
- data/i18n/en-US/mail/application.en-US.yml +66 -0
- data/i18n/en-US/mail/auction_context/post_auction/participant.en-US.yml +13 -0
- data/i18n/en-US/mail/auction_context/post_auction/winner.en-US.yml +13 -0
- data/i18n/en-US/mail/auction_context/pre_auction/auction_start_reminder.en-US.yml +11 -0
- data/i18n/pt-BR/contracts/contracts.pt-BR.yml +12 -0
- data/i18n/pt-BR/mail/application.pt-BR.yml +66 -0
- data/i18n/pt-BR/mail/auction_context/post_auction/participant.pt-BR.yml +13 -0
- data/i18n/pt-BR/mail/auction_context/post_auction/winner.pt-BR.yml +13 -0
- data/i18n/pt-BR/mail/auction_context/pre_auction/auction_start_reminder.pt-BR.yml +11 -0
- data/i18n/pt-BR/mail/user_context/registration.pt-BR.yml +0 -4
- data/lib/auction_fun_core/business/configuration.rb +31 -0
- data/lib/auction_fun_core/business/token_generator.rb +19 -1
- data/lib/auction_fun_core/contracts/application_contract.rb +9 -1
- data/lib/auction_fun_core/contracts/auction_context/create_contract.rb +35 -20
- data/lib/auction_fun_core/contracts/auction_context/post_auction/participant_contract.rb +64 -0
- data/lib/auction_fun_core/contracts/auction_context/post_auction/winner_contract.rb +62 -0
- data/lib/auction_fun_core/contracts/auction_context/pre_auction/auction_start_reminder_contract.rb +48 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/closed_contract.rb +59 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/penny_contract.rb +60 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/standard_contract.rb +60 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/pause_contract.rb +16 -4
- data/lib/auction_fun_core/contracts/auction_context/processor/start_contract.rb +17 -5
- data/lib/auction_fun_core/contracts/auction_context/processor/unpause_contract.rb +16 -4
- data/lib/auction_fun_core/contracts/bid_context/create_bid_closed_contract.rb +20 -11
- data/lib/auction_fun_core/contracts/bid_context/create_bid_penny_contract.rb +18 -9
- data/lib/auction_fun_core/contracts/bid_context/create_bid_standard_contract.rb +19 -10
- data/lib/auction_fun_core/contracts/staff_context/authentication_contract.rb +18 -4
- data/lib/auction_fun_core/contracts/staff_context/registration_contract.rb +20 -8
- data/lib/auction_fun_core/contracts/user_context/authentication_contract.rb +18 -4
- data/lib/auction_fun_core/contracts/user_context/email_confirmation_contract.rb +17 -2
- data/lib/auction_fun_core/contracts/user_context/phone_confirmation_contract.rb +17 -2
- data/lib/auction_fun_core/contracts/user_context/registration_contract.rb +26 -8
- data/lib/auction_fun_core/entities/auction.rb +52 -2
- data/lib/auction_fun_core/entities/bid.rb +3 -2
- data/lib/auction_fun_core/entities/staff.rb +15 -2
- data/lib/auction_fun_core/entities/user.rb +31 -2
- data/lib/auction_fun_core/events/app.rb +8 -2
- data/lib/auction_fun_core/events/listener.rb +19 -16
- data/lib/auction_fun_core/operations/auction_context/create_operation.rb +37 -11
- data/lib/auction_fun_core/operations/auction_context/post_auction/participant_operation.rb +85 -0
- data/lib/auction_fun_core/operations/auction_context/post_auction/winner_operation.rb +85 -0
- data/lib/auction_fun_core/operations/auction_context/pre_auction/auction_start_reminder_operation.rb +96 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/closed_operation.rb +172 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/penny_operation.rb +171 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/standard_operation.rb +171 -0
- data/lib/auction_fun_core/operations/auction_context/processor/pause_operation.rb +36 -1
- data/lib/auction_fun_core/operations/auction_context/processor/start_operation.rb +23 -11
- data/lib/auction_fun_core/operations/auction_context/processor/unpause_operation.rb +36 -1
- data/lib/auction_fun_core/operations/bid_context/create_bid_penny_operation.rb +57 -7
- data/lib/auction_fun_core/operations/staff_context/registration_operation.rb +10 -0
- data/lib/auction_fun_core/relations/auctions.rb +252 -30
- data/lib/auction_fun_core/relations/bids.rb +18 -0
- data/lib/auction_fun_core/relations/staffs.rb +1 -1
- data/lib/auction_fun_core/repos/auction_context/auction_repository.rb +40 -11
- data/lib/auction_fun_core/repos/bid_context/bid_repository.rb +27 -5
- data/lib/auction_fun_core/repos/staff_context/staff_repository.rb +63 -21
- data/lib/auction_fun_core/repos/user_context/user_repository.rb +69 -25
- data/lib/auction_fun_core/services/mail/auction_context/post_auction/participant_mailer.rb +37 -0
- data/lib/auction_fun_core/services/mail/auction_context/post_auction/winner_mailer.rb +37 -0
- data/lib/auction_fun_core/services/mail/auction_context/pre_auction/auction_start_reminder_mailer.rb +35 -0
- data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/participant.html.erb +173 -0
- data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/winner.html.erb +174 -0
- data/lib/auction_fun_core/services/mail/templates/auction_context/pre_auction/auction_start_reminder.html.erb +192 -0
- data/lib/auction_fun_core/services/mail/templates/user_context/registration.html.erb +2 -2
- data/lib/auction_fun_core/services/mail/user_context/registration_mailer.rb +6 -0
- data/lib/auction_fun_core/version.rb +1 -1
- data/lib/auction_fun_core/workers/application_job.rb +12 -0
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/participant_operation_job.rb +38 -0
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/winner_operation_job.rb +37 -0
- data/lib/auction_fun_core/workers/operations/auction_context/pre_auction/auction_start_reminder_operation_job.rb +44 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/closed_operation_job.rb +37 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/penny_operation_job.rb +40 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/standard_operation_job.rb +38 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/start_operation_job.rb +6 -3
- data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/participant_mailer_job.rb +56 -0
- data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/winner_mailer_job.rb +57 -0
- data/lib/auction_fun_core/workers/services/mail/auction_context/pre_auction/auction_start_reminder_mailer_job.rb +48 -0
- data/lib/auction_fun_core/workers/services/mail/user_context/registration_mailer_job.rb +8 -6
- data/system/providers/background_job.rb +25 -0
- metadata +51 -5
- data/lib/auction_fun_core/contracts/auction_context/processor/finish_contract.rb +0 -27
- data/lib/auction_fun_core/operations/auction_context/processor/finish_operation.rb +0 -61
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish_operation_job.rb +0 -32
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AuctionFunCore
|
4
|
+
module Operations
|
5
|
+
module AuctionContext
|
6
|
+
module Processor
|
7
|
+
module Finish
|
8
|
+
##
|
9
|
+
# Operation class for finalizing a closed auction.
|
10
|
+
# By default, this changes the auction status from 'running' to 'finished'.
|
11
|
+
#
|
12
|
+
class ClosedOperation < AuctionFunCore::Operations::Base
|
13
|
+
include Import["repos.auction_context.auction_repository"]
|
14
|
+
include Import["contracts.auction_context.processor.finish.closed_contract"]
|
15
|
+
include Import["workers.operations.auction_context.post_auction.winner_operation_job"]
|
16
|
+
include Import["workers.operations.auction_context.post_auction.participant_operation_job"]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes the closed operation with the provided attributes.
|
20
|
+
#
|
21
|
+
# @param attributes [Hash] The attributes for the closed operation.
|
22
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
23
|
+
# @yield [Dry::Matcher::Evaluator] The block to handle the result of the operation.
|
24
|
+
# @return [Dry::Matcher::Evaluator] The result of the operation.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# attributes = { auction_id: 123 }
|
28
|
+
#
|
29
|
+
# AuctionFunCore::Operations::AuctionContext::Processor::Finish::ClosedOperation.call(attributes) do |result|
|
30
|
+
# result.success { |auction| puts "Finished closed auction sucessfully! #{auction.to_h}" }
|
31
|
+
# result.failure { |failure| puts "Failed to finished closed auction: #{failure.errors.to_h}"}
|
32
|
+
# end
|
33
|
+
def self.call(attributes, &block)
|
34
|
+
operation = new.call(attributes)
|
35
|
+
|
36
|
+
return operation unless block
|
37
|
+
|
38
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Performs the closing of a closed auction.
|
43
|
+
#
|
44
|
+
# @param attributes [Hash] The attributes for the closed operation.
|
45
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
46
|
+
# @return [Dry::Monads::Result] The result of the operation.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# attributes = { auction_id: 123 }
|
50
|
+
#
|
51
|
+
# operation = AuctionFunCore::Operations::AuctionContext::Processor::Finish::ClosedOperation.call(attributes)
|
52
|
+
#
|
53
|
+
# if operation.success?
|
54
|
+
# auction = operation.success
|
55
|
+
# puts "Finished closed auction sucessfully! #{auction.to_h}"
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# if operation.failure?
|
59
|
+
# failure = operation.failure
|
60
|
+
# puts "Failed to finished closed auction: #{failure.errors.to_h}"
|
61
|
+
# end
|
62
|
+
def call(attributes)
|
63
|
+
auction = yield validate_contract(attributes)
|
64
|
+
summary = yield load_closed_auction_winners_and_participants(auction.id)
|
65
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
66
|
+
|
67
|
+
auction_repository.transaction do |_t|
|
68
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
69
|
+
|
70
|
+
yield winner_operation(auction.id, summary.winner_id)
|
71
|
+
|
72
|
+
summary.participant_ids.each do |participant_id|
|
73
|
+
yield participant_operation(auction.id, participant_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
publish_auction_finish_event(auction)
|
77
|
+
end
|
78
|
+
|
79
|
+
Success(auction)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
##
|
85
|
+
# Validates the contract with the provided attributes.
|
86
|
+
#
|
87
|
+
# @param attributes [Hash] The attributes to validate.
|
88
|
+
# @option auction_id [Integer] The ID of the auction.
|
89
|
+
# @return [Dry::Monads::Result] The result of the validation.
|
90
|
+
#
|
91
|
+
def validate_contract(attributes)
|
92
|
+
contract = closed_contract.call(attributes)
|
93
|
+
|
94
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
95
|
+
|
96
|
+
Success(contract.context[:auction])
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Loads the winners and participants of the closed auction.
|
101
|
+
#
|
102
|
+
# @param auction_id [Integer] The ID of the auction.
|
103
|
+
# @return [Dry::Monads::Result] The result of loading the winners and participants.
|
104
|
+
#
|
105
|
+
def load_closed_auction_winners_and_participants(auction_id)
|
106
|
+
summary = relation.load_closed_auction_winners_and_participants(auction_id).first
|
107
|
+
|
108
|
+
Success(summary)
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Updates the attributes of the finished auction.
|
113
|
+
#
|
114
|
+
# @param auction [Auction] The auction object.
|
115
|
+
# @param summary [Summary] The summary of winners and participants.
|
116
|
+
# @return [Dry::Monads::Result] The result of updating the attributes.
|
117
|
+
#
|
118
|
+
def update_finished_auction(auction, summary)
|
119
|
+
attrs = {status: "finished"}
|
120
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
121
|
+
|
122
|
+
Success(attrs)
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Retrieves the relation.
|
127
|
+
#
|
128
|
+
# @return [ROM::Relation] The relation object.
|
129
|
+
#
|
130
|
+
def relation
|
131
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Executes the winner operation asynchronously.
|
136
|
+
#
|
137
|
+
# @param auction_id [Integer] The ID of the auction.
|
138
|
+
# @param winner_id [Integer] The ID of the winner.
|
139
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
140
|
+
#
|
141
|
+
def winner_operation(auction_id, winner_id)
|
142
|
+
return Success() if winner_id.blank?
|
143
|
+
|
144
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Executes the participant operation asynchronously.
|
149
|
+
#
|
150
|
+
# @param auction_id [Integer] The ID of the auction.
|
151
|
+
# @param participant_id [Integer] The ID of the participant.
|
152
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
153
|
+
#
|
154
|
+
def participant_operation(auction_id, participant_id)
|
155
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Publishes the auction finish event.
|
160
|
+
#
|
161
|
+
# @param auction [ROM::Struct::Auction] The auction object.
|
162
|
+
# @return [void]
|
163
|
+
#
|
164
|
+
def publish_auction_finish_event(auction)
|
165
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AuctionFunCore
|
4
|
+
module Operations
|
5
|
+
module AuctionContext
|
6
|
+
module Processor
|
7
|
+
module Finish
|
8
|
+
##
|
9
|
+
# Operation class for finalizing a penny auction.
|
10
|
+
# By default, this changes the auction status from 'running' to 'finished'.
|
11
|
+
#
|
12
|
+
class PennyOperation < AuctionFunCore::Operations::Base
|
13
|
+
include Import["repos.auction_context.auction_repository"]
|
14
|
+
include Import["contracts.auction_context.processor.finish.penny_contract"]
|
15
|
+
include Import["workers.operations.auction_context.post_auction.winner_operation_job"]
|
16
|
+
include Import["workers.operations.auction_context.post_auction.participant_operation_job"]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes the penny operation with the provided attributes.
|
20
|
+
#
|
21
|
+
# @param attributes [Hash] The attributes for the penny operation.
|
22
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
23
|
+
# @yield [Dry::Matcher::Evaluator] The block to handle the result of the operation.
|
24
|
+
# @return [Dry::Matcher::Evaluator] The result of the operation.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# attributes = { auction_id: 123 }
|
28
|
+
#
|
29
|
+
# AuctionFunCore::Operations::AuctionContext::Processor::Finish::PennyOperation.call(attributes) do |result|
|
30
|
+
# result.success { |auction| puts "Finished penny auction sucessfully! #{auction.to_h}" }
|
31
|
+
# result.failure { |failure| puts "Failed to finished penny auction: #{failure.errors.to_h}"}
|
32
|
+
# end
|
33
|
+
def self.call(attributes, &block)
|
34
|
+
operation = new.call(attributes)
|
35
|
+
|
36
|
+
return operation unless block
|
37
|
+
|
38
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Performs the closing of a penny auction.
|
43
|
+
#
|
44
|
+
# @param attributes [Hash] The attributes for the penny operation.
|
45
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
46
|
+
# @return [Dry::Monads::Result] The result of the operation.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# attributes = { auction_id: 123 }
|
50
|
+
#
|
51
|
+
# operation = AuctionFunCore::Operations::AuctionContext::Processor::Finish::PennyOperation.call(attributes)
|
52
|
+
#
|
53
|
+
# if operation.success?
|
54
|
+
# auction = operation.success
|
55
|
+
# puts "Finished penny auction sucessfully! #{auction.to_h}"
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# if operation.failure?
|
59
|
+
# failure = operation.failure
|
60
|
+
# puts "Failed to finished penny auction: #{failure.errors.to_h}"
|
61
|
+
# end
|
62
|
+
def call(attributes)
|
63
|
+
auction = yield validate_contract(attributes)
|
64
|
+
summary = yield load_penny_auction_winners_and_participants(auction.id)
|
65
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
66
|
+
|
67
|
+
auction_repository.transaction do |_t|
|
68
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
69
|
+
|
70
|
+
yield winner_operation(auction.id, summary.winner_id)
|
71
|
+
|
72
|
+
summary.participant_ids.each do |participant_id|
|
73
|
+
yield participant_operation(auction.id, participant_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
publish_auction_finish_event(auction)
|
77
|
+
end
|
78
|
+
|
79
|
+
Success(auction)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
##
|
85
|
+
# Validates the contract with the provided attributes.
|
86
|
+
#
|
87
|
+
# @param attributes [Hash] The attributes to validate.
|
88
|
+
# @return [Dry::Monads::Result] The result of the validation.
|
89
|
+
#
|
90
|
+
def validate_contract(attributes)
|
91
|
+
contract = penny_contract.call(attributes)
|
92
|
+
|
93
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
94
|
+
|
95
|
+
Success(contract.context[:auction])
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Loads the winners and participants of the penny auction.
|
100
|
+
#
|
101
|
+
# @param auction_id [Integer] The ID of the auction.
|
102
|
+
# @return [Dry::Monads::Result] The result of loading the winners and participants.
|
103
|
+
#
|
104
|
+
def load_penny_auction_winners_and_participants(auction_id)
|
105
|
+
summary = relation.load_penny_auction_winners_and_participants(auction_id).first
|
106
|
+
|
107
|
+
Success(summary)
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Updates the attributes of the finished auction.
|
112
|
+
#
|
113
|
+
# @param auction [ROM::Struct::Auction] The auction object.
|
114
|
+
# @param summary [ROM::OpenStruct] The summary of winners and participants.
|
115
|
+
# @return [Dry::Monads::Result] The result of updating the attributes.
|
116
|
+
#
|
117
|
+
def update_finished_auction(auction, summary)
|
118
|
+
attrs = {status: "finished"}
|
119
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
120
|
+
|
121
|
+
Success(attrs)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Retrieves the relation.
|
126
|
+
#
|
127
|
+
# @return [ROM::Relation] The relation object.
|
128
|
+
#
|
129
|
+
def relation
|
130
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Executes the winner operation asynchronously.
|
135
|
+
#
|
136
|
+
# @param auction_id [Integer] The ID of the auction.
|
137
|
+
# @param winner_id [Integer] The ID of the winner.
|
138
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
139
|
+
#
|
140
|
+
def winner_operation(auction_id, winner_id)
|
141
|
+
return Success() if winner_id.blank?
|
142
|
+
|
143
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Executes the participant operation asynchronously.
|
148
|
+
#
|
149
|
+
# @param auction_id [Integer] The ID of the auction.
|
150
|
+
# @param participant_id [Integer] The ID of the participant.
|
151
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
152
|
+
#
|
153
|
+
def participant_operation(auction_id, participant_id)
|
154
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Publishes the auction finish event.
|
159
|
+
#
|
160
|
+
# @param auction [ROM::Struct::Auction] The auction object.
|
161
|
+
# @return [void]
|
162
|
+
#
|
163
|
+
def publish_auction_finish_event(auction)
|
164
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AuctionFunCore
|
4
|
+
module Operations
|
5
|
+
module AuctionContext
|
6
|
+
module Processor
|
7
|
+
module Finish
|
8
|
+
##
|
9
|
+
# Operation class for finalizing a standard auction.
|
10
|
+
# By default, this changes the auction status from 'running' to 'finished'.
|
11
|
+
#
|
12
|
+
class StandardOperation < AuctionFunCore::Operations::Base
|
13
|
+
include Import["repos.auction_context.auction_repository"]
|
14
|
+
include Import["contracts.auction_context.processor.finish.standard_contract"]
|
15
|
+
include Import["workers.operations.auction_context.post_auction.winner_operation_job"]
|
16
|
+
include Import["workers.operations.auction_context.post_auction.participant_operation_job"]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes the standard operation with the provided attributes.
|
20
|
+
#
|
21
|
+
# @param attributes [Hash] The attributes for the standard operation.
|
22
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
23
|
+
# @yield [Dry::Matcher::Evaluator] The block to handle the result of the operation.
|
24
|
+
# @return [Dry::Matcher::Evaluator] The result of the operation.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# attributes = { auction_id: 123 }
|
28
|
+
#
|
29
|
+
# AuctionFunCore::Operations::AuctionContext::Processor::Finish::StandardOperation.call(attributes) do |result|
|
30
|
+
# result.success { |auction| puts "Finished standard auction sucessfully! #{auction.to_h}" }
|
31
|
+
# result.failure { |failure| puts "Failed to finished standard auction: #{failure.errors.to_h}"}
|
32
|
+
# end
|
33
|
+
def self.call(attributes, &block)
|
34
|
+
operation = new.call(attributes)
|
35
|
+
|
36
|
+
return operation unless block
|
37
|
+
|
38
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Performs the closing of a standard auction.
|
43
|
+
#
|
44
|
+
# @param attributes [Hash] The attributes for the standard operation.
|
45
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
46
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure] The result of the operation.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# attributes = { auction_id: 123 }
|
50
|
+
#
|
51
|
+
# operation = AuctionFunCore::Operations::AuctionContext::Processor::Finish::StandardOperation.call(attributes)
|
52
|
+
#
|
53
|
+
# if operation.success?
|
54
|
+
# auction = operation.success
|
55
|
+
# puts "Finished standard auction sucessfully! #{auction.to_h}"
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# if operation.failure?
|
59
|
+
# failure = operation.failure
|
60
|
+
# puts "Failed to finished standard auction: #{failure.errors.to_h}"
|
61
|
+
# end
|
62
|
+
def call(attributes)
|
63
|
+
auction = yield validate_contract(attributes)
|
64
|
+
summary = yield load_standard_auction_winners_and_participants(auction.id)
|
65
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
66
|
+
|
67
|
+
auction_repository.transaction do |_t|
|
68
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
69
|
+
|
70
|
+
yield winner_operation(auction.id, summary.winner_id)
|
71
|
+
|
72
|
+
summary.participant_ids.each do |participant_id|
|
73
|
+
yield participant_operation(auction.id, participant_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
publish_auction_finish_event(auction)
|
77
|
+
end
|
78
|
+
|
79
|
+
Success(auction)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
##
|
85
|
+
# Validates the contract with the provided attributes.
|
86
|
+
#
|
87
|
+
# @param attributes [Hash] The attributes to validate.
|
88
|
+
# @return [Dry::Monads::Result] The result of the validation.
|
89
|
+
#
|
90
|
+
def validate_contract(attributes)
|
91
|
+
contract = standard_contract.call(attributes)
|
92
|
+
|
93
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
94
|
+
|
95
|
+
Success(contract.context[:auction])
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Loads the winners and participants of the standard auction.
|
100
|
+
#
|
101
|
+
# @param auction_id [Integer] The ID of the auction.
|
102
|
+
# @return [Dry::Monads::Result] The result of loading the winners and participants.
|
103
|
+
#
|
104
|
+
def load_standard_auction_winners_and_participants(auction_id)
|
105
|
+
summary = relation.load_standard_auction_winners_and_participants(auction_id).first
|
106
|
+
|
107
|
+
Success(summary)
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Updates the attributes of the finished auction.
|
112
|
+
#
|
113
|
+
# @param auction [Auction] The auction object.
|
114
|
+
# @param summary [Summary] The summary of winners and participants.
|
115
|
+
# @return [Dry::Monads::Result] The result of updating the attributes.
|
116
|
+
#
|
117
|
+
def update_finished_auction(auction, summary)
|
118
|
+
attrs = {status: "finished"}
|
119
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
120
|
+
|
121
|
+
Success(attrs)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Retrieves the relation.
|
126
|
+
#
|
127
|
+
# @return [ROM::Relation] The relation object.
|
128
|
+
#
|
129
|
+
def relation
|
130
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Executes the winner operation asynchronously.
|
135
|
+
#
|
136
|
+
# @param auction_id [Integer] The ID of the auction.
|
137
|
+
# @param winner_id [Integer] The ID of the winner.
|
138
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
139
|
+
#
|
140
|
+
def winner_operation(auction_id, winner_id)
|
141
|
+
return Success() if winner_id.blank?
|
142
|
+
|
143
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Executes the participant operation asynchronously.
|
148
|
+
#
|
149
|
+
# @param auction_id [Integer] The ID of the auction.
|
150
|
+
# @param participant_id [Integer] The ID of the participant.
|
151
|
+
# @return [Dry::Monads::Result] The result of executing the operation.
|
152
|
+
#
|
153
|
+
def participant_operation(auction_id, participant_id)
|
154
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Publishes the auction finish event.
|
159
|
+
#
|
160
|
+
# @param auction [ROM::Struct::Auction] The auction object.
|
161
|
+
# @return [void]
|
162
|
+
#
|
163
|
+
def publish_auction_finish_event(auction)
|
164
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -12,7 +12,21 @@ module AuctionFunCore
|
|
12
12
|
include Import["repos.auction_context.auction_repository"]
|
13
13
|
include Import["contracts.auction_context.processor.pause_contract"]
|
14
14
|
|
15
|
-
|
15
|
+
##
|
16
|
+
# Executes the pause operation with the provided attributes.
|
17
|
+
#
|
18
|
+
# @param attributes [Hash] The attributes for the pause operation.
|
19
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
20
|
+
# @yield [Dry::Matcher::Evaluator] The block to handle the result of the operation.
|
21
|
+
# @return [Dry::Matcher::Evaluator] The result of the operation.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# attributes = { auction_id: 123 }
|
25
|
+
#
|
26
|
+
# AuctionFunCore::Operations::AuctionContext::Processor::PauseOperation.call(attributes) do |result|
|
27
|
+
# result.success { |auction| puts "Paused auction sucessfully! #{auction.to_h}" }
|
28
|
+
# result.failure { |failure| puts "Failed to pause auction: #{failure.errors.to_h}"}
|
29
|
+
# end
|
16
30
|
def self.call(attributes, &block)
|
17
31
|
operation = new.call(attributes)
|
18
32
|
|
@@ -21,6 +35,27 @@ module AuctionFunCore
|
|
21
35
|
Dry::Matcher::ResultMatcher.call(operation, &block)
|
22
36
|
end
|
23
37
|
|
38
|
+
##
|
39
|
+
# Performing an auction pause
|
40
|
+
#
|
41
|
+
# @param attributes [Hash] The attributes for the pause operation.
|
42
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
43
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure] The result of the operation.
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# attributes = { auction_id: 123 }
|
47
|
+
#
|
48
|
+
# operation = AuctionFunCore::Operations::AuctionContext::Processor::PauseOperation.call(attributes)
|
49
|
+
#
|
50
|
+
# if operation.success?
|
51
|
+
# auction = operation.success
|
52
|
+
# puts "Paused auction sucessfully! #{auction.to_h}"
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# if operation.failure?
|
56
|
+
# failure = operation.failure
|
57
|
+
# puts "Failed to pause auction: #{failure.errors.to_h}"
|
58
|
+
# end
|
24
59
|
def call(attributes)
|
25
60
|
attrs = yield validate(attributes)
|
26
61
|
|
@@ -11,7 +11,9 @@ module AuctionFunCore
|
|
11
11
|
class StartOperation < AuctionFunCore::Operations::Base
|
12
12
|
include Import["repos.auction_context.auction_repository"]
|
13
13
|
include Import["contracts.auction_context.processor.start_contract"]
|
14
|
-
include Import["workers.operations.auction_context.processor.
|
14
|
+
include Import["workers.operations.auction_context.processor.finish.closed_operation_job"]
|
15
|
+
include Import["workers.operations.auction_context.processor.finish.penny_operation_job"]
|
16
|
+
include Import["workers.operations.auction_context.processor.finish.standard_operation_job"]
|
15
17
|
|
16
18
|
# @todo Add custom doc
|
17
19
|
def self.call(attributes, &block)
|
@@ -28,10 +30,10 @@ module AuctionFunCore
|
|
28
30
|
# @option opts [Integer] :stopwatch auction stopwatch
|
29
31
|
# @return [ROM::Struct::Auction] auction object
|
30
32
|
def call(attributes)
|
31
|
-
attrs = yield
|
33
|
+
auction, attrs = yield validate_contract(attributes)
|
32
34
|
|
33
35
|
auction_repository.transaction do |_t|
|
34
|
-
@auction, _ = auction_repository.update(
|
36
|
+
@auction, _ = auction_repository.update(auction.id, update_params(auction, attrs))
|
35
37
|
|
36
38
|
yield publish_auction_start_event(@auction)
|
37
39
|
yield scheduled_finished_auction(@auction)
|
@@ -46,36 +48,46 @@ module AuctionFunCore
|
|
46
48
|
# of the informed attributes.
|
47
49
|
# @param attributes [Hash] auction attributes
|
48
50
|
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
49
|
-
def
|
51
|
+
def validate_contract(attributes)
|
50
52
|
contract = start_contract.call(attributes)
|
51
53
|
|
52
54
|
return Failure(contract.errors.to_h) if contract.failure?
|
53
55
|
|
54
|
-
Success(contract.to_h)
|
56
|
+
Success([contract.context[:auction], contract.to_h])
|
55
57
|
end
|
56
58
|
|
57
59
|
# Updates the status of the auction and depending on the type of auction,
|
58
60
|
# it already sets the final date.
|
59
61
|
# @param attrs [Hash] auction attributes
|
60
62
|
# @return [Hash]
|
61
|
-
def update_params(attrs)
|
62
|
-
return {status: "running"} unless attrs[:kind] == "penny"
|
63
|
+
def update_params(auction, attrs)
|
64
|
+
return {kind: auction.kind, status: "running"} unless attrs[:kind] == "penny"
|
63
65
|
|
64
|
-
{status: "running", finished_at: attrs[:stopwatch].seconds.from_now}
|
66
|
+
{kind: auction.kind, status: "running", finished_at: attrs[:stopwatch].seconds.from_now}
|
65
67
|
end
|
66
68
|
|
67
69
|
def publish_auction_start_event(auction)
|
68
70
|
Success(Application[:event].publish("auctions.started", auction.to_h))
|
69
71
|
end
|
70
72
|
|
73
|
+
# TODO: Added a small delay to perform operations (such as sending broadcasts and/or other operations).
|
71
74
|
# Calls the background job class that will schedule the finish of the auction.
|
72
|
-
#
|
75
|
+
# In the case of the penny auction, the end of the auction occurs after the first timer resets.
|
73
76
|
# @param auction [ROM::Struct::Auction]
|
74
77
|
# @return [String] sidekiq jid
|
75
78
|
def scheduled_finished_auction(auction)
|
76
|
-
|
79
|
+
perform_at = auction.finished_at
|
77
80
|
|
78
|
-
|
81
|
+
case auction.kind
|
82
|
+
in "penny"
|
83
|
+
perform_at = auction.started_at + auction.stopwatch.seconds
|
84
|
+
|
85
|
+
Success(penny_operation_job.class.perform_at(perform_at, auction.id))
|
86
|
+
in "standard"
|
87
|
+
Success(standard_operation_job.class.perform_at(perform_at, auction.id))
|
88
|
+
in "closed"
|
89
|
+
Success(closed_operation_job.class.perform_at(perform_at, auction.id))
|
90
|
+
end
|
79
91
|
end
|
80
92
|
end
|
81
93
|
end
|