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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +2 -0
  3. data/CHANGELOG.md +48 -0
  4. data/Procfile +1 -0
  5. data/README.md +34 -32
  6. data/Rakefile +1 -1
  7. data/auction_fun_core.gemspec +1 -0
  8. data/db/migrate/20240229143000_create_auctions.rb +1 -0
  9. data/db/seeds.rb +87 -36
  10. data/i18n/en-US/contracts/contracts.en-US.yml +12 -0
  11. data/i18n/en-US/mail/application.en-US.yml +66 -0
  12. data/i18n/en-US/mail/auction_context/post_auction/participant.en-US.yml +13 -0
  13. data/i18n/en-US/mail/auction_context/post_auction/winner.en-US.yml +13 -0
  14. data/i18n/en-US/mail/auction_context/pre_auction/auction_start_reminder.en-US.yml +11 -0
  15. data/i18n/pt-BR/contracts/contracts.pt-BR.yml +12 -0
  16. data/i18n/pt-BR/mail/application.pt-BR.yml +66 -0
  17. data/i18n/pt-BR/mail/auction_context/post_auction/participant.pt-BR.yml +13 -0
  18. data/i18n/pt-BR/mail/auction_context/post_auction/winner.pt-BR.yml +13 -0
  19. data/i18n/pt-BR/mail/auction_context/pre_auction/auction_start_reminder.pt-BR.yml +11 -0
  20. data/i18n/pt-BR/mail/user_context/registration.pt-BR.yml +0 -4
  21. data/lib/auction_fun_core/business/configuration.rb +31 -0
  22. data/lib/auction_fun_core/business/token_generator.rb +19 -1
  23. data/lib/auction_fun_core/contracts/application_contract.rb +9 -1
  24. data/lib/auction_fun_core/contracts/auction_context/create_contract.rb +35 -20
  25. data/lib/auction_fun_core/contracts/auction_context/post_auction/participant_contract.rb +64 -0
  26. data/lib/auction_fun_core/contracts/auction_context/post_auction/winner_contract.rb +62 -0
  27. data/lib/auction_fun_core/contracts/auction_context/pre_auction/auction_start_reminder_contract.rb +48 -0
  28. data/lib/auction_fun_core/contracts/auction_context/processor/finish/closed_contract.rb +59 -0
  29. data/lib/auction_fun_core/contracts/auction_context/processor/finish/penny_contract.rb +60 -0
  30. data/lib/auction_fun_core/contracts/auction_context/processor/finish/standard_contract.rb +60 -0
  31. data/lib/auction_fun_core/contracts/auction_context/processor/pause_contract.rb +16 -4
  32. data/lib/auction_fun_core/contracts/auction_context/processor/start_contract.rb +17 -5
  33. data/lib/auction_fun_core/contracts/auction_context/processor/unpause_contract.rb +16 -4
  34. data/lib/auction_fun_core/contracts/bid_context/create_bid_closed_contract.rb +20 -11
  35. data/lib/auction_fun_core/contracts/bid_context/create_bid_penny_contract.rb +18 -9
  36. data/lib/auction_fun_core/contracts/bid_context/create_bid_standard_contract.rb +19 -10
  37. data/lib/auction_fun_core/contracts/staff_context/authentication_contract.rb +18 -4
  38. data/lib/auction_fun_core/contracts/staff_context/registration_contract.rb +20 -8
  39. data/lib/auction_fun_core/contracts/user_context/authentication_contract.rb +18 -4
  40. data/lib/auction_fun_core/contracts/user_context/email_confirmation_contract.rb +17 -2
  41. data/lib/auction_fun_core/contracts/user_context/phone_confirmation_contract.rb +17 -2
  42. data/lib/auction_fun_core/contracts/user_context/registration_contract.rb +26 -8
  43. data/lib/auction_fun_core/entities/auction.rb +52 -2
  44. data/lib/auction_fun_core/entities/bid.rb +3 -2
  45. data/lib/auction_fun_core/entities/staff.rb +15 -2
  46. data/lib/auction_fun_core/entities/user.rb +31 -2
  47. data/lib/auction_fun_core/events/app.rb +8 -2
  48. data/lib/auction_fun_core/events/listener.rb +19 -16
  49. data/lib/auction_fun_core/operations/auction_context/create_operation.rb +37 -11
  50. data/lib/auction_fun_core/operations/auction_context/post_auction/participant_operation.rb +85 -0
  51. data/lib/auction_fun_core/operations/auction_context/post_auction/winner_operation.rb +85 -0
  52. data/lib/auction_fun_core/operations/auction_context/pre_auction/auction_start_reminder_operation.rb +96 -0
  53. data/lib/auction_fun_core/operations/auction_context/processor/finish/closed_operation.rb +172 -0
  54. data/lib/auction_fun_core/operations/auction_context/processor/finish/penny_operation.rb +171 -0
  55. data/lib/auction_fun_core/operations/auction_context/processor/finish/standard_operation.rb +171 -0
  56. data/lib/auction_fun_core/operations/auction_context/processor/pause_operation.rb +36 -1
  57. data/lib/auction_fun_core/operations/auction_context/processor/start_operation.rb +23 -11
  58. data/lib/auction_fun_core/operations/auction_context/processor/unpause_operation.rb +36 -1
  59. data/lib/auction_fun_core/operations/bid_context/create_bid_penny_operation.rb +57 -7
  60. data/lib/auction_fun_core/operations/staff_context/registration_operation.rb +10 -0
  61. data/lib/auction_fun_core/relations/auctions.rb +252 -30
  62. data/lib/auction_fun_core/relations/bids.rb +18 -0
  63. data/lib/auction_fun_core/relations/staffs.rb +1 -1
  64. data/lib/auction_fun_core/repos/auction_context/auction_repository.rb +40 -11
  65. data/lib/auction_fun_core/repos/bid_context/bid_repository.rb +27 -5
  66. data/lib/auction_fun_core/repos/staff_context/staff_repository.rb +63 -21
  67. data/lib/auction_fun_core/repos/user_context/user_repository.rb +69 -25
  68. data/lib/auction_fun_core/services/mail/auction_context/post_auction/participant_mailer.rb +37 -0
  69. data/lib/auction_fun_core/services/mail/auction_context/post_auction/winner_mailer.rb +37 -0
  70. data/lib/auction_fun_core/services/mail/auction_context/pre_auction/auction_start_reminder_mailer.rb +35 -0
  71. data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/participant.html.erb +173 -0
  72. data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/winner.html.erb +174 -0
  73. data/lib/auction_fun_core/services/mail/templates/auction_context/pre_auction/auction_start_reminder.html.erb +192 -0
  74. data/lib/auction_fun_core/services/mail/templates/user_context/registration.html.erb +2 -2
  75. data/lib/auction_fun_core/services/mail/user_context/registration_mailer.rb +6 -0
  76. data/lib/auction_fun_core/version.rb +1 -1
  77. data/lib/auction_fun_core/workers/application_job.rb +12 -0
  78. data/lib/auction_fun_core/workers/operations/auction_context/post_auction/participant_operation_job.rb +38 -0
  79. data/lib/auction_fun_core/workers/operations/auction_context/post_auction/winner_operation_job.rb +37 -0
  80. data/lib/auction_fun_core/workers/operations/auction_context/pre_auction/auction_start_reminder_operation_job.rb +44 -0
  81. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/closed_operation_job.rb +37 -0
  82. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/penny_operation_job.rb +40 -0
  83. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/standard_operation_job.rb +38 -0
  84. data/lib/auction_fun_core/workers/operations/auction_context/processor/start_operation_job.rb +6 -3
  85. data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/participant_mailer_job.rb +56 -0
  86. data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/winner_mailer_job.rb +57 -0
  87. data/lib/auction_fun_core/workers/services/mail/auction_context/pre_auction/auction_start_reminder_mailer_job.rb +48 -0
  88. data/lib/auction_fun_core/workers/services/mail/user_context/registration_mailer_job.rb +8 -6
  89. data/system/providers/background_job.rb +25 -0
  90. metadata +51 -5
  91. data/lib/auction_fun_core/contracts/auction_context/processor/finish_contract.rb +0 -27
  92. data/lib/auction_fun_core/operations/auction_context/processor/finish_operation.rb +0 -61
  93. 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
- # @todo Add custom doc
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.finish_operation_job"]
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 validate(attributes)
33
+ auction, attrs = yield validate_contract(attributes)
32
34
 
33
35
  auction_repository.transaction do |_t|
34
- @auction, _ = auction_repository.update(attrs[:auction_id], update_params(attrs))
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 validate(attributes)
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
- # Added a small delay to perform operations (such as sending broadcasts and/or other operations).
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
- return Success() if auction.kind == "penny"
79
+ perform_at = auction.finished_at
77
80
 
78
- Success(finish_operation_job.class.perform_at(auction.finished_at, auction.id))
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