auction_fun_core 0.8.5 → 0.8.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- 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 +9 -0
- data/i18n/en-US/mail/application.en-US.yml +59 -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/pt-BR/contracts/contracts.pt-BR.yml +9 -0
- data/i18n/pt-BR/mail/application.pt-BR.yml +59 -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/user_context/registration.pt-BR.yml +0 -4
- data/lib/auction_fun_core/contracts/auction_context/post_auction/participant_contract.rb +42 -0
- data/lib/auction_fun_core/contracts/auction_context/post_auction/winner_contract.rb +41 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/closed_contract.rb +47 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/penny_contract.rb +48 -0
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/standard_contract.rb +48 -0
- data/lib/auction_fun_core/entities/auction.rb +6 -0
- data/lib/auction_fun_core/operations/auction_context/create_operation.rb +12 -2
- data/lib/auction_fun_core/operations/auction_context/post_auction/participant_operation.rb +52 -0
- data/lib/auction_fun_core/operations/auction_context/post_auction/winner_operation.rb +51 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/closed_operation.rb +100 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/penny_operation.rb +100 -0
- data/lib/auction_fun_core/operations/auction_context/processor/finish/standard_operation.rb +102 -0
- data/lib/auction_fun_core/operations/auction_context/processor/start_operation.rb +23 -11
- 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 +167 -26
- data/lib/auction_fun_core/relations/staffs.rb +1 -1
- data/lib/auction_fun_core/services/mail/auction_context/post_auction/participant_mailer.rb +31 -0
- data/lib/auction_fun_core/services/mail/auction_context/post_auction/winner_mailer.rb +31 -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/user_context/registration.html.erb +2 -2
- data/lib/auction_fun_core/version.rb +1 -1
- data/lib/auction_fun_core/workers/application_job.rb +2 -0
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/participant_operation_job.rb +33 -0
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/winner_operation_job.rb +33 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/closed_operation_job.rb +34 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/penny_operation_job.rb +37 -0
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/standard_operation_job.rb +34 -0
- data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/participant_mailer_job.rb +51 -0
- data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/winner_mailer_job.rb +51 -0
- data/system/providers/background_job.rb +19 -0
- metadata +43 -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
@@ -5,6 +5,8 @@ module AuctionFunCore
|
|
5
5
|
# Auction Relations class. This return simple objects with attribute readers
|
6
6
|
# to represent data in your auction.
|
7
7
|
class Auction < ROM::Struct
|
8
|
+
INQUIRER_ATTRIBUTES = Relations::Auctions::STATUSES.values.freeze
|
9
|
+
|
8
10
|
def initial_bid
|
9
11
|
Money.new(initial_bid_cents, initial_bid_currency)
|
10
12
|
end
|
@@ -12,6 +14,10 @@ module AuctionFunCore
|
|
12
14
|
def minimal_bid
|
13
15
|
Money.new(minimal_bid_cents, minimal_bid_currency)
|
14
16
|
end
|
17
|
+
|
18
|
+
def winner?
|
19
|
+
winner_id.present?
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -21,7 +21,8 @@ module AuctionFunCore
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def call(attributes)
|
24
|
-
values = yield
|
24
|
+
values = yield validate_contract(attributes)
|
25
|
+
values = yield assign_default_values(values)
|
25
26
|
|
26
27
|
auction_repository.transaction do |_t|
|
27
28
|
@auction = yield persist(values)
|
@@ -38,7 +39,7 @@ module AuctionFunCore
|
|
38
39
|
# of the informed attributes.
|
39
40
|
# @param attrs [Hash] auction attributes
|
40
41
|
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
41
|
-
def
|
42
|
+
def validate_contract(attrs)
|
42
43
|
contract = create_contract.call(attrs)
|
43
44
|
|
44
45
|
return Failure(contract.errors.to_h) if contract.failure?
|
@@ -46,6 +47,15 @@ module AuctionFunCore
|
|
46
47
|
Success(contract.to_h)
|
47
48
|
end
|
48
49
|
|
50
|
+
# By default, the auction status is set to 'scheduled'.
|
51
|
+
# @todo Refactor this method in the future to consider the status as of the auction start date.
|
52
|
+
# @param attrs [Hash] auction attributes
|
53
|
+
# @return [Dry::Monads::Result::Success]
|
54
|
+
def assign_default_values(attrs)
|
55
|
+
attrs[:status] = "scheduled"
|
56
|
+
Success(attrs)
|
57
|
+
end
|
58
|
+
|
49
59
|
# Calls the auction repository class to persist the attributes in the database.
|
50
60
|
# @param result [Hash] Auction validated attributes
|
51
61
|
# @return [ROM::Struct::Auction]
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AuctionFunCore
|
4
|
+
module Operations
|
5
|
+
module AuctionContext
|
6
|
+
module PostAuction
|
7
|
+
##
|
8
|
+
# Operation class for finish auctions.
|
9
|
+
#
|
10
|
+
class ParticipantOperation < AuctionFunCore::Operations::Base
|
11
|
+
include Import["repos.user_context.user_repository"]
|
12
|
+
include Import["contracts.auction_context.post_auction.participant_contract"]
|
13
|
+
include Import["workers.services.mail.auction_context.post_auction.participant_mailer_job"]
|
14
|
+
|
15
|
+
def self.call(attributes, &block)
|
16
|
+
operation = new.call(attributes)
|
17
|
+
|
18
|
+
return operation unless block
|
19
|
+
|
20
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
## @todo Add more actions
|
24
|
+
# Send email to participant with auction statistics.
|
25
|
+
def call(attributes)
|
26
|
+
auction, participant = yield validate_contract(attributes)
|
27
|
+
|
28
|
+
user_repository.transaction do |_t|
|
29
|
+
yield send_participant_email_with_statistics_and_payment_instructions(auction.id, participant.id)
|
30
|
+
end
|
31
|
+
|
32
|
+
Success([auction, participant])
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def validate_contract(attributes)
|
38
|
+
contract = participant_contract.call(attributes)
|
39
|
+
|
40
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
41
|
+
|
42
|
+
Success([contract.context[:auction], contract.context[:participant]])
|
43
|
+
end
|
44
|
+
|
45
|
+
def send_participant_email_with_statistics_and_payment_instructions(auction_id, participant_id)
|
46
|
+
Success(participant_mailer_job.class.perform_async(auction_id, participant_id))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AuctionFunCore
|
4
|
+
module Operations
|
5
|
+
module AuctionContext
|
6
|
+
module PostAuction
|
7
|
+
##
|
8
|
+
# Operation class for finish auctions.
|
9
|
+
#
|
10
|
+
class WinnerOperation < AuctionFunCore::Operations::Base
|
11
|
+
include Import["repos.user_context.user_repository"]
|
12
|
+
include Import["contracts.auction_context.post_auction.winner_contract"]
|
13
|
+
include Import["workers.services.mail.auction_context.post_auction.winner_mailer_job"]
|
14
|
+
|
15
|
+
def self.call(attributes, &block)
|
16
|
+
operation = new.call(attributes)
|
17
|
+
|
18
|
+
return operation unless block
|
19
|
+
|
20
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
## @todo Add doc
|
24
|
+
def call(attributes)
|
25
|
+
auction, winner = yield validate_contract(attributes)
|
26
|
+
|
27
|
+
user_repository.transaction do |_t|
|
28
|
+
send_winner_email_with_statistics_and_payment_instructions(auction.id, winner.id)
|
29
|
+
end
|
30
|
+
|
31
|
+
Success([auction, winner])
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def validate_contract(attributes)
|
37
|
+
contract = winner_contract.call(attributes)
|
38
|
+
|
39
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
40
|
+
|
41
|
+
Success([contract.context[:auction], contract.context[:winner]])
|
42
|
+
end
|
43
|
+
|
44
|
+
def send_winner_email_with_statistics_and_payment_instructions(auction_id, winner_id)
|
45
|
+
Success(winner_mailer_job.class.perform_async(auction_id, winner_id))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,100 @@
|
|
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 change 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
|
+
# @todo Add custom doc
|
19
|
+
def self.call(attributes, &block)
|
20
|
+
operation = new.call(attributes)
|
21
|
+
|
22
|
+
return operation unless block
|
23
|
+
|
24
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# It only performs the basic processing of completing an auction.
|
28
|
+
# It just changes the status at the database level and triggers the finished event.
|
29
|
+
# @param auction_id [Integer] Auction ID
|
30
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
31
|
+
def call(attributes)
|
32
|
+
auction = yield validate_contract(attributes)
|
33
|
+
summary = yield load_closed_auction_winners_and_participants(auction.id)
|
34
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
35
|
+
|
36
|
+
auction_repository.transaction do |_t|
|
37
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
38
|
+
|
39
|
+
yield winner_operation(auction.id, summary.winner_id)
|
40
|
+
|
41
|
+
summary.participant_ids.each do |participant_id|
|
42
|
+
yield participant_operation(auction.id, participant_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
publish_auction_finish_event(auction)
|
46
|
+
end
|
47
|
+
|
48
|
+
Success(auction)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# Calls the finish contract class to perform the validation
|
54
|
+
# of the informed attributes.
|
55
|
+
# @param attributes [Hash] auction attributes
|
56
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
57
|
+
def validate_contract(attributes)
|
58
|
+
contract = closed_contract.call(attributes)
|
59
|
+
|
60
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
61
|
+
|
62
|
+
Success(contract.context[:auction])
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_closed_auction_winners_and_participants(auction_id)
|
66
|
+
summary = relation.load_closed_auction_winners_and_participants(auction_id).first
|
67
|
+
|
68
|
+
Success(summary)
|
69
|
+
end
|
70
|
+
|
71
|
+
def update_finished_auction(auction, summary)
|
72
|
+
attrs = {status: "finished"}
|
73
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
74
|
+
|
75
|
+
Success(attrs)
|
76
|
+
end
|
77
|
+
|
78
|
+
def relation
|
79
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
80
|
+
end
|
81
|
+
|
82
|
+
def winner_operation(auction_id, winner_id)
|
83
|
+
return Success() if winner_id.blank?
|
84
|
+
|
85
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
86
|
+
end
|
87
|
+
|
88
|
+
def participant_operation(auction_id, participant_id)
|
89
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
90
|
+
end
|
91
|
+
|
92
|
+
def publish_auction_finish_event(auction)
|
93
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,100 @@
|
|
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 change 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
|
+
# @todo Add custom doc
|
19
|
+
def self.call(attributes, &block)
|
20
|
+
operation = new.call(attributes)
|
21
|
+
|
22
|
+
return operation unless block
|
23
|
+
|
24
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# It only performs the basic processing of completing an auction.
|
28
|
+
# It just changes the status at the database level and triggers the finished event.
|
29
|
+
# @param auction_id [Integer] Auction ID
|
30
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
31
|
+
def call(attributes)
|
32
|
+
auction = yield validate_contract(attributes)
|
33
|
+
summary = yield load_penny_auction_winners_and_participants(auction.id)
|
34
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
35
|
+
|
36
|
+
auction_repository.transaction do |_t|
|
37
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
38
|
+
|
39
|
+
yield winner_operation(auction.id, summary.winner_id)
|
40
|
+
|
41
|
+
summary.participant_ids.each do |participant_id|
|
42
|
+
yield participant_operation(auction.id, participant_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
publish_auction_finish_event(auction)
|
46
|
+
end
|
47
|
+
|
48
|
+
Success(auction)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# Calls the finish contract class to perform the validation
|
54
|
+
# of the informed attributes.
|
55
|
+
# @param attributes [Hash] auction attributes
|
56
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
57
|
+
def validate_contract(attributes)
|
58
|
+
contract = penny_contract.call(attributes)
|
59
|
+
|
60
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
61
|
+
|
62
|
+
Success(contract.context[:auction])
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_penny_auction_winners_and_participants(auction_id)
|
66
|
+
summary = relation.load_penny_auction_winners_and_participants(auction_id).first
|
67
|
+
|
68
|
+
Success(summary)
|
69
|
+
end
|
70
|
+
|
71
|
+
def update_finished_auction(auction, summary)
|
72
|
+
attrs = {status: "finished"}
|
73
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
74
|
+
|
75
|
+
Success(attrs)
|
76
|
+
end
|
77
|
+
|
78
|
+
def relation
|
79
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
80
|
+
end
|
81
|
+
|
82
|
+
def winner_operation(auction_id, winner_id)
|
83
|
+
return Success() if winner_id.blank?
|
84
|
+
|
85
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
86
|
+
end
|
87
|
+
|
88
|
+
def participant_operation(auction_id, participant_id)
|
89
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
90
|
+
end
|
91
|
+
|
92
|
+
def publish_auction_finish_event(auction)
|
93
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,102 @@
|
|
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 change 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
|
+
# @todo Add custom doc
|
19
|
+
def self.call(attributes, &block)
|
20
|
+
operation = new.call(attributes)
|
21
|
+
|
22
|
+
return operation unless block
|
23
|
+
|
24
|
+
Dry::Matcher::ResultMatcher.call(operation, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO: update doc
|
28
|
+
# It only performs the basic processing of completing an auction.
|
29
|
+
# It just changes the status at the database level and triggers the finished event.
|
30
|
+
# @param attrs [Hash] auction attributes
|
31
|
+
# @option auction_id [Integer] Auction ID
|
32
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
33
|
+
def call(attributes)
|
34
|
+
auction = yield validate_contract(attributes)
|
35
|
+
summary = yield load_standard_auction_winners_and_participants(auction.id)
|
36
|
+
update_auction_attributes = yield update_finished_auction(auction, summary)
|
37
|
+
|
38
|
+
auction_repository.transaction do |_t|
|
39
|
+
auction, _ = auction_repository.update(auction.id, update_auction_attributes)
|
40
|
+
|
41
|
+
yield winner_operation(auction.id, summary.winner_id)
|
42
|
+
|
43
|
+
summary.participant_ids.each do |participant_id|
|
44
|
+
yield participant_operation(auction.id, participant_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
publish_auction_finish_event(auction)
|
48
|
+
end
|
49
|
+
|
50
|
+
Success(auction)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Calls the finish standard contract class to perform the validation
|
56
|
+
# of the informed attributes.
|
57
|
+
# @param attributes [Hash] auction attributes
|
58
|
+
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
59
|
+
def validate_contract(attributes)
|
60
|
+
contract = standard_contract.call(attributes)
|
61
|
+
|
62
|
+
return Failure(contract.errors.to_h) if contract.failure?
|
63
|
+
|
64
|
+
Success(contract.context[:auction])
|
65
|
+
end
|
66
|
+
|
67
|
+
def load_standard_auction_winners_and_participants(auction_id)
|
68
|
+
summary = relation.load_standard_auction_winners_and_participants(auction_id).first
|
69
|
+
|
70
|
+
Success(summary)
|
71
|
+
end
|
72
|
+
|
73
|
+
def update_finished_auction(auction, summary)
|
74
|
+
attrs = {status: "finished"}
|
75
|
+
attrs[:winner_id] = summary.winner_id if summary.winner_id.present?
|
76
|
+
|
77
|
+
Success(attrs)
|
78
|
+
end
|
79
|
+
|
80
|
+
def relation
|
81
|
+
AuctionFunCore::Application[:container].relations[:auctions]
|
82
|
+
end
|
83
|
+
|
84
|
+
def winner_operation(auction_id, winner_id)
|
85
|
+
return Success() if winner_id.blank?
|
86
|
+
|
87
|
+
Success(winner_operation_job.class.perform_async(auction_id, winner_id))
|
88
|
+
end
|
89
|
+
|
90
|
+
def participant_operation(auction_id, participant_id)
|
91
|
+
Success(participant_operation_job.class.perform_async(auction_id, participant_id))
|
92
|
+
end
|
93
|
+
|
94
|
+
def publish_auction_finish_event(auction)
|
95
|
+
Application[:event].publish("auctions.finished", auction.to_h)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -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
|
@@ -7,8 +7,10 @@ module AuctionFunCore
|
|
7
7
|
# Operation class for create new bids for penny auctions.
|
8
8
|
#
|
9
9
|
class CreateBidPennyOperation < AuctionFunCore::Operations::Base
|
10
|
-
include Import["contracts.bid_context.create_bid_penny_contract"]
|
11
10
|
include Import["repos.bid_context.bid_repository"]
|
11
|
+
include Import["repos.auction_context.auction_repository"]
|
12
|
+
include Import["contracts.bid_context.create_bid_penny_contract"]
|
13
|
+
include Import["workers.operations.auction_context.processor.finish.penny_operation_job"]
|
12
14
|
|
13
15
|
# @todo Add custom doc
|
14
16
|
def self.call(attributes, &block)
|
@@ -21,10 +23,13 @@ module AuctionFunCore
|
|
21
23
|
|
22
24
|
# @todo Add custom doc
|
23
25
|
def call(attributes)
|
24
|
-
values = yield
|
26
|
+
auction, values = yield validate_contract(attributes)
|
25
27
|
|
26
28
|
bid_repository.transaction do |_t|
|
27
29
|
@bid = yield persist(values)
|
30
|
+
updated_auction = yield update_end_auction(auction)
|
31
|
+
|
32
|
+
yield reschedule_end_auction(updated_auction)
|
28
33
|
yield publish_bid_created(@bid)
|
29
34
|
end
|
30
35
|
|
@@ -35,19 +40,42 @@ module AuctionFunCore
|
|
35
40
|
# of the informed attributes.
|
36
41
|
# @param attrs [Hash] bid attributes
|
37
42
|
# @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
|
38
|
-
def
|
43
|
+
def validate_contract(attrs)
|
39
44
|
contract = create_bid_penny_contract.call(attrs)
|
40
45
|
|
41
46
|
return Failure(contract.errors.to_h) if contract.failure?
|
42
47
|
|
43
|
-
Success(contract.to_h)
|
48
|
+
Success([contract.context[:auction], contract.to_h])
|
49
|
+
end
|
50
|
+
|
51
|
+
# Updates the end time of an auction if it has already started.
|
52
|
+
#
|
53
|
+
# This method checks whether an auction is currently running. If the auction is running,
|
54
|
+
# it calculates a new end time based on the current time and the duration specified
|
55
|
+
# by the auction's stopwatch. The auction's finish time is then updated in the repository.
|
56
|
+
# If the auction has not started, it returns the auction as is without any modifications.
|
57
|
+
#
|
58
|
+
# @param auction [ROM::Struct::Auction] An instance of Auction to be checked and potentially updated.
|
59
|
+
# @return [Dry::Monads::Result::Success<ROM::Struct::Auction>, Dry::Monads::Result::Failure]
|
60
|
+
def update_end_auction(auction)
|
61
|
+
return Success(auction) unless started_auction?(auction)
|
62
|
+
|
63
|
+
updated_attributes = {
|
64
|
+
finished_at: Time.current + auction.stopwatch.seconds,
|
65
|
+
kind: auction.kind,
|
66
|
+
status: auction.status
|
67
|
+
}
|
68
|
+
|
69
|
+
updated_auction, _ = auction_repository.update(auction.id, updated_attributes)
|
70
|
+
|
71
|
+
Success(updated_auction)
|
44
72
|
end
|
45
73
|
|
46
74
|
# Calls the bid repository class to persist the attributes in the database.
|
47
75
|
# @param result [Hash] Bid validated attributes
|
48
|
-
# @return [ROM::Struct::Bid]
|
49
|
-
def persist(
|
50
|
-
Success(bid_repository.create(
|
76
|
+
# @return [Dry::Monads::Result::Success<ROM::Struct::Bid>, Dry::Monads::Result::Failure]
|
77
|
+
def persist(values)
|
78
|
+
Success(bid_repository.create(values))
|
51
79
|
end
|
52
80
|
|
53
81
|
# Triggers the publication of event *bids.created*.
|
@@ -58,6 +86,28 @@ module AuctionFunCore
|
|
58
86
|
|
59
87
|
Success()
|
60
88
|
end
|
89
|
+
|
90
|
+
# TODO: Added a small delay to perform operations (such as sending broadcasts and/or other operations).
|
91
|
+
# Reschedules the end time of an auction's background job if the auction has already started.
|
92
|
+
#
|
93
|
+
# This method checks if the auction is running. If so, it schedules a background job to
|
94
|
+
# execute at the auction's current finish time using the job class defined by the
|
95
|
+
# penny_operation_job attribute of the auction. If the auction has not started, it
|
96
|
+
# simply returns a Success object with no parameters.
|
97
|
+
#
|
98
|
+
# @return [Dry::Monads::Result::Success<ROM::Struct::Auction>, Dry::Monads::Result::Success<String>]
|
99
|
+
def reschedule_end_auction(auction)
|
100
|
+
# binding.pry
|
101
|
+
return Success(auction) unless started_auction?(auction)
|
102
|
+
|
103
|
+
perform_at = auction.finished_at
|
104
|
+
|
105
|
+
Success(penny_operation_job.class.perform_at(perform_at, auction.id))
|
106
|
+
end
|
107
|
+
|
108
|
+
def started_auction?(auction)
|
109
|
+
auction.status == "running"
|
110
|
+
end
|
61
111
|
end
|
62
112
|
end
|
63
113
|
end
|
@@ -21,6 +21,7 @@ module AuctionFunCore
|
|
21
21
|
# @todo Add custom doc
|
22
22
|
def call(attributes)
|
23
23
|
values = yield validate_contract(attributes)
|
24
|
+
values = yield assign_default_values(values)
|
24
25
|
values_with_encrypt_password = yield encrypt_password(values)
|
25
26
|
|
26
27
|
staff_repository.transaction do |_t|
|
@@ -44,6 +45,15 @@ module AuctionFunCore
|
|
44
45
|
Success(contract.to_h)
|
45
46
|
end
|
46
47
|
|
48
|
+
# By default, there can only be a single root staff. All other members have their type set to 'common'.
|
49
|
+
# @param attrs [Hash] user attributes
|
50
|
+
# @return [Dry::Monads::Result::Success]
|
51
|
+
def assign_default_values(attrs)
|
52
|
+
attrs[:kind] = "common"
|
53
|
+
|
54
|
+
Success(attrs)
|
55
|
+
end
|
56
|
+
|
47
57
|
# Transforms the password attribute, encrypting it to be saved in the database.
|
48
58
|
# @param result [Hash] Staff valid contract attributes
|
49
59
|
# @return [Hash] Valid staff database
|