auction_fun_core 0.8.7 → 0.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.standard.yml +2 -0
- data/CHANGELOG.md +23 -0
- data/Procfile +1 -0
- data/README.md +34 -32
- data/Rakefile +1 -1
- data/i18n/en-US/contracts/contracts.en-US.yml +3 -0
- data/i18n/en-US/mail/application.en-US.yml +7 -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 +3 -0
- data/i18n/pt-BR/mail/application.pt-BR.yml +7 -0
- data/i18n/pt-BR/mail/auction_context/pre_auction/auction_start_reminder.pt-BR.yml +11 -0
- 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 +23 -1
- data/lib/auction_fun_core/contracts/auction_context/post_auction/winner_contract.rb +22 -1
- 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 +19 -7
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/penny_contract.rb +19 -7
- data/lib/auction_fun_core/contracts/auction_context/processor/finish/standard_contract.rb +19 -7
- 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 +48 -4
- 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 +25 -9
- data/lib/auction_fun_core/operations/auction_context/post_auction/participant_operation.rb +36 -3
- data/lib/auction_fun_core/operations/auction_context/post_auction/winner_operation.rb +36 -2
- 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 +82 -10
- data/lib/auction_fun_core/operations/auction_context/processor/finish/penny_operation.rb +81 -10
- data/lib/auction_fun_core/operations/auction_context/processor/finish/standard_operation.rb +81 -12
- data/lib/auction_fun_core/operations/auction_context/processor/pause_operation.rb +36 -1
- data/lib/auction_fun_core/operations/auction_context/processor/unpause_operation.rb +36 -1
- data/lib/auction_fun_core/relations/auctions.rb +178 -97
- data/lib/auction_fun_core/relations/bids.rb +18 -0
- 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 +7 -1
- data/lib/auction_fun_core/services/mail/auction_context/post_auction/winner_mailer.rb +7 -1
- 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 +1 -1
- data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/winner.html.erb +1 -1
- 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/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 +10 -0
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/participant_operation_job.rb +7 -2
- data/lib/auction_fun_core/workers/operations/auction_context/post_auction/winner_operation_job.rb +6 -2
- 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 +6 -3
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/penny_operation_job.rb +6 -3
- data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/standard_operation_job.rb +6 -2
- 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 +12 -7
- data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/winner_mailer_job.rb +11 -5
- 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 +6 -0
- metadata +10 -2
|
@@ -12,7 +12,21 @@ module AuctionFunCore
|
|
|
12
12
|
include Import["repos.auction_context.auction_repository"]
|
|
13
13
|
include Import["contracts.auction_context.processor.unpause_contract"]
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
##
|
|
16
|
+
# Executes the unpause operation with the provided attributes.
|
|
17
|
+
#
|
|
18
|
+
# @param attributes [Hash] The attributes for the unpause 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::UnpauseOperation.call(attributes) do |result|
|
|
27
|
+
# result.success { |auction| puts "Unpaused auction sucessfully! #{auction.to_h}" }
|
|
28
|
+
# result.failure { |failure| puts "Failed to unpause 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
|
+
# Performs the unpause of an auction.
|
|
40
|
+
#
|
|
41
|
+
# @param attributes [Hash] The attributes for the unpause 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::UnpauseOperation.call(attributes)
|
|
49
|
+
#
|
|
50
|
+
# if operation.success?
|
|
51
|
+
# auction = operation.success
|
|
52
|
+
# puts "Unpaused auction sucessfully! #{auction.to_h}"
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# if operation.failure?
|
|
56
|
+
# failure = operation.failure
|
|
57
|
+
# puts "Failed to unpause auction: #{failure.errors.to_h}"
|
|
58
|
+
# end
|
|
24
59
|
def call(attributes)
|
|
25
60
|
attrs = yield validate(attributes)
|
|
26
61
|
|
|
@@ -40,12 +40,30 @@ module AuctionFunCore
|
|
|
40
40
|
struct_namespace Entities
|
|
41
41
|
auto_struct(true)
|
|
42
42
|
|
|
43
|
+
# Retrieves a paginated list of auctions along with related information.
|
|
44
|
+
# By default, it retrieves the first page with 10 auctions per page and includes information for the top 3 bidders.
|
|
45
|
+
#
|
|
46
|
+
# @param page [Integer] The page number to retrieve (default is 1).
|
|
47
|
+
# @param per_page [Integer] The number of auctions per page (default is 10).
|
|
48
|
+
# @param options [Hash] Additional options for customization (default is {bidders_count: 3}).
|
|
49
|
+
# @option options [Integer] :bidders_count The number of top bidders to include in the result (default is 3).
|
|
50
|
+
# @return [Array<Hash>] An array of hashes representing the auctions and related information.
|
|
51
|
+
# @example Retrieve the first page of auctions with 10 per page and include information for the top 3 bidders
|
|
52
|
+
# all_auctions = all
|
|
53
|
+
#
|
|
54
|
+
# @example Retrieve the second page of auctions with 5 per page and include information for the top 5 bidders
|
|
55
|
+
# all_auctions = all(2, 5, { bidders_count: 5 })
|
|
56
|
+
#
|
|
57
|
+
# @example Retrieve the third page of auctions with 15 per page and include information for the top 2 bidders
|
|
58
|
+
# all_auctions = all(3, 15, { bidders_count: 2 })
|
|
59
|
+
#
|
|
60
|
+
# @raise [RuntimeError] if either `page` or `per_page` argument is not an integer.
|
|
43
61
|
def all(page = 1, per_page = 10, options = {bidders_count: 3})
|
|
44
62
|
raise "Invalid argument" unless page.is_a?(Integer) && per_page.is_a?(Integer)
|
|
45
63
|
|
|
46
64
|
offset = ((page - 1) * per_page)
|
|
47
65
|
|
|
48
|
-
|
|
66
|
+
sql = <<-SQL
|
|
49
67
|
SELECT a.id, a.title, a.description, a.kind, a.status, a.started_at, a.finished_at, a.stopwatch, a.initial_bid_cents,
|
|
50
68
|
(SELECT COUNT(*) FROM (SELECT * FROM bids WHERE bids.auction_id = a.id) dt) AS total_bids,
|
|
51
69
|
CASE
|
|
@@ -69,17 +87,37 @@ module AuctionFunCore
|
|
|
69
87
|
WHEN a.kind = 'closed' THEN
|
|
70
88
|
json_build_object('minimal', (a.initial_bid_cents + (a.initial_bid_cents * 0.10))::int)
|
|
71
89
|
END as bids
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
FROM auctions as a
|
|
91
|
+
LEFT JOIN LATERAL (SELECT * FROM bids WHERE auction_id = a.id ORDER BY value_cents DESC LIMIT #{options[:bidders_count]}) as bi ON a.id = bi.auction_id
|
|
92
|
+
LEFT JOIN users ON bi.user_id = users.id AND bi.auction_id = a.id
|
|
93
|
+
GROUP BY a.id
|
|
94
|
+
LIMIT #{per_page} OFFSET #{offset}
|
|
95
|
+
SQL
|
|
96
|
+
|
|
97
|
+
read(sql)
|
|
77
98
|
end
|
|
78
99
|
|
|
100
|
+
# Retrieves detailed information about a specific auction.
|
|
101
|
+
#
|
|
102
|
+
# @param auction_id [Integer] The ID of the auction to retrieve information for.
|
|
103
|
+
# @param options [Hash] Additional options for customization (default is {bidders_count: 3}).
|
|
104
|
+
# @option options [Integer] :bidders_count The number of top bidders to include in the result (default is 3).
|
|
105
|
+
# @return [Hash] A hash representing the auction and related information.
|
|
106
|
+
#
|
|
107
|
+
# @example Retrieve information for auction with ID 123
|
|
108
|
+
# auction_info = info(123)
|
|
109
|
+
#
|
|
110
|
+
# @example Retrieve information for auction with ID 456 and include information for the top 5 bidders
|
|
111
|
+
# auction_info = info(456, { bidders_count: 5 })
|
|
112
|
+
#
|
|
113
|
+
# @example Retrieve information for auction with ID 789 and include information for the top 2 bidders
|
|
114
|
+
# auction_info = info(789, { bidders_count: 2 })
|
|
115
|
+
#
|
|
116
|
+
# @raise [RuntimeError] if `auction_id` argument is not an integer.
|
|
79
117
|
def info(auction_id, options = {bidders_count: 3})
|
|
80
118
|
raise "Invalid argument" unless auction_id.is_a?(Integer)
|
|
81
119
|
|
|
82
|
-
|
|
120
|
+
sql = <<-SQL
|
|
83
121
|
SELECT a.id, a.title, a.description, a.kind, a.status, a.started_at, a.finished_at, a.stopwatch, a.initial_bid_cents,
|
|
84
122
|
(SELECT COUNT(*) FROM (SELECT * FROM bids WHERE bids.auction_id = #{auction_id}) dt) AS total_bids,
|
|
85
123
|
CASE
|
|
@@ -103,11 +141,14 @@ module AuctionFunCore
|
|
|
103
141
|
WHEN a.kind = 'closed' THEN
|
|
104
142
|
json_build_object('minimal', (a.initial_bid_cents + (a.initial_bid_cents * 0.10))::int)
|
|
105
143
|
END as bids
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
144
|
+
FROM auctions as a
|
|
145
|
+
LEFT JOIN LATERAL (SELECT * FROM bids WHERE auction_id = a.id ORDER BY value_cents DESC LIMIT #{options[:bidders_count]}) as bi ON a.id = bi.auction_id AND a.id = #{auction_id}
|
|
146
|
+
LEFT JOIN users ON bi.user_id = users.id AND bi.auction_id = a.id
|
|
147
|
+
WHERE a.id = #{auction_id}
|
|
148
|
+
GROUP BY a.id
|
|
149
|
+
SQL
|
|
150
|
+
|
|
151
|
+
read(sql)
|
|
111
152
|
end
|
|
112
153
|
|
|
113
154
|
# Retrieves the standard auction winner and other participating bidders for a specified auction.
|
|
@@ -125,22 +166,26 @@ module AuctionFunCore
|
|
|
125
166
|
def load_standard_auction_winners_and_participants(auction_id)
|
|
126
167
|
raise "Invalid argument" unless auction_id.is_a?(Integer)
|
|
127
168
|
|
|
128
|
-
|
|
129
|
-
COALESCE(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
169
|
+
sql = <<-SQL
|
|
170
|
+
SELECT a.id, a.kind, a.status, w.user_id AS winner_id, COALESCE(COUNT(b.id), 0) AS total_bids,
|
|
171
|
+
COALESCE(
|
|
172
|
+
ARRAY_REMOVE(ARRAY_AGG(DISTINCT b.user_id ORDER BY b.user_id), w.user_id), ARRAY[]::INT[]
|
|
173
|
+
) AS participant_ids
|
|
174
|
+
FROM auctions a
|
|
175
|
+
LEFT JOIN bids b ON a.id = b.auction_id
|
|
176
|
+
LEFT JOIN (
|
|
177
|
+
SELECT auction_id, user_id, MAX(value_cents) AS value_cents
|
|
178
|
+
FROM bids
|
|
179
|
+
WHERE auction_id = #{auction_id}
|
|
180
|
+
GROUP BY auction_id, user_id
|
|
181
|
+
ORDER BY value_cents DESC
|
|
182
|
+
LIMIT 1
|
|
183
|
+
) AS w ON a.id = w.auction_id
|
|
184
|
+
WHERE a.id = #{auction_id}
|
|
185
|
+
GROUP BY a.id, w.user_id
|
|
186
|
+
SQL
|
|
187
|
+
|
|
188
|
+
read(sql)
|
|
144
189
|
end
|
|
145
190
|
|
|
146
191
|
# Retrieves the penny auction winner and other participating bidders for a specified auction.
|
|
@@ -158,21 +203,25 @@ module AuctionFunCore
|
|
|
158
203
|
def load_penny_auction_winners_and_participants(auction_id)
|
|
159
204
|
raise "Invalid argument" unless auction_id.is_a?(Integer)
|
|
160
205
|
|
|
161
|
-
|
|
162
|
-
COALESCE(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
206
|
+
sql = <<-SQL
|
|
207
|
+
SELECT a.id, a.kind, a.status, w.user_id AS winner_id, COALESCE(COUNT(b.id), 0) AS total_bids,
|
|
208
|
+
COALESCE(
|
|
209
|
+
ARRAY_REMOVE(ARRAY_AGG(DISTINCT b.user_id ORDER BY b.user_id), w.user_id), ARRAY[]::INT[]
|
|
210
|
+
) AS participant_ids
|
|
211
|
+
FROM auctions a
|
|
212
|
+
LEFT JOIN bids b ON a.id = b.auction_id
|
|
213
|
+
LEFT JOIN (
|
|
214
|
+
SELECT auction_id, user_id
|
|
215
|
+
FROM bids
|
|
216
|
+
WHERE auction_id = #{auction_id}
|
|
217
|
+
ORDER BY bids.created_at DESC
|
|
218
|
+
LIMIT 1
|
|
219
|
+
) AS w ON a.id = w.auction_id
|
|
220
|
+
WHERE a.id = #{auction_id}
|
|
221
|
+
GROUP BY a.id, w.user_id
|
|
222
|
+
SQL
|
|
223
|
+
|
|
224
|
+
read(sql)
|
|
176
225
|
end
|
|
177
226
|
|
|
178
227
|
# Retrieves the closed auction winner and other participating bidders for a specified auction.
|
|
@@ -190,70 +239,102 @@ module AuctionFunCore
|
|
|
190
239
|
def load_closed_auction_winners_and_participants(auction_id)
|
|
191
240
|
raise "Invalid argument" unless auction_id.is_a?(Integer)
|
|
192
241
|
|
|
193
|
-
|
|
194
|
-
COALESCE(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
242
|
+
sql = <<-SQL
|
|
243
|
+
SELECT a.id, a.kind, a.status, w.user_id AS winner_id, COALESCE(COUNT(b.id), 0) AS total_bids,
|
|
244
|
+
COALESCE(
|
|
245
|
+
ARRAY_REMOVE(ARRAY_AGG(DISTINCT b.user_id ORDER BY b.user_id), w.user_id), ARRAY[]::INT[]
|
|
246
|
+
) AS participant_ids
|
|
247
|
+
FROM auctions a
|
|
248
|
+
LEFT JOIN bids b ON a.id = b.auction_id
|
|
249
|
+
LEFT JOIN (
|
|
250
|
+
SELECT auction_id, user_id, MAX(value_cents) AS value_cents
|
|
251
|
+
FROM bids
|
|
252
|
+
WHERE auction_id = #{auction_id}
|
|
253
|
+
GROUP BY auction_id, user_id
|
|
254
|
+
ORDER BY value_cents DESC
|
|
255
|
+
LIMIT 1
|
|
256
|
+
) AS w ON a.id = w.auction_id
|
|
257
|
+
WHERE a.id = #{auction_id}
|
|
258
|
+
GROUP BY a.id, w.user_id
|
|
259
|
+
SQL
|
|
260
|
+
|
|
261
|
+
read(sql)
|
|
209
262
|
end
|
|
210
263
|
|
|
264
|
+
# Loads statistics for the winner of a specific auction.
|
|
265
|
+
#
|
|
266
|
+
# @param auction_id [Integer] The ID of the auction to load statistics for.
|
|
267
|
+
# @param winner_id [Integer] The ID of the winner to load statistics for.
|
|
268
|
+
# @return [Hash] A hash representing the statistics for the winner of the auction.
|
|
269
|
+
#
|
|
270
|
+
# @example Load statistics for the winner of auction with ID 123 and winner with ID 456
|
|
271
|
+
# winner_stats = load_winner_statistics(123, 456)
|
|
272
|
+
#
|
|
273
|
+
# @raise [RuntimeError] if either `auction_id` or `winner_id` arguments are not integers.
|
|
211
274
|
def load_winner_statistics(auction_id, winner_id)
|
|
212
275
|
raise "Invalid argument" unless auction_id.is_a?(Integer) && winner_id.is_a?(Integer)
|
|
213
276
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
277
|
+
sql = <<-SQL
|
|
278
|
+
SELECT a.id, COUNT(b.id) AS auction_total_bids, MAX(b.value_cents) AS winner_bid,
|
|
279
|
+
date(a.finished_at) as auction_date,
|
|
280
|
+
(SELECT COUNT(*) FROM bids b2
|
|
281
|
+
WHERE b2.auction_id = #{auction_id}
|
|
282
|
+
AND b2.user_id = #{winner_id}
|
|
283
|
+
) AS winner_total_bids
|
|
284
|
+
FROM auctions a
|
|
285
|
+
LEFT JOIN bids b ON a.id = b.auction_id AND a.id = #{auction_id}
|
|
286
|
+
LEFT JOIN users u ON u.id = b.user_id AND u.id = #{winner_id}
|
|
287
|
+
LEFT JOIN (
|
|
288
|
+
SELECT auction_id, user_id, MAX(value_cents) AS value_cents
|
|
289
|
+
FROM bids
|
|
290
|
+
WHERE auction_id = #{auction_id}
|
|
291
|
+
GROUP BY auction_id, user_id
|
|
292
|
+
ORDER BY value_cents DESC
|
|
293
|
+
LIMIT 1
|
|
294
|
+
) AS w ON a.id = w.auction_id
|
|
295
|
+
WHERE a.id = #{auction_id}
|
|
296
|
+
GROUP BY a.id
|
|
297
|
+
SQL
|
|
298
|
+
|
|
299
|
+
read(sql)
|
|
233
300
|
end
|
|
234
301
|
|
|
302
|
+
# Loads statistics for a participant in a specific auction.
|
|
303
|
+
#
|
|
304
|
+
# @param auction_id [Integer] The ID of the auction to load statistics for.
|
|
305
|
+
# @param participant_id [Integer] The ID of the participant to load statistics for.
|
|
306
|
+
# @return [Hash] A hash representing the statistics for the participant in the auction.
|
|
307
|
+
#
|
|
308
|
+
# @example Load statistics for the participant with ID 456 in auction with ID 123
|
|
309
|
+
# participant_stats = load_participant_statistics(123, 456)
|
|
310
|
+
#
|
|
311
|
+
# @raise [RuntimeError] if either `auction_id` or `participant_id` arguments are not integers.
|
|
235
312
|
def load_participant_statistics(auction_id, participant_id)
|
|
236
313
|
raise "Invalid argument" unless auction_id.is_a?(Integer) && participant_id.is_a?(Integer)
|
|
237
314
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
315
|
+
sql = <<-SQL
|
|
316
|
+
SELECT a.id, COUNT(b.id) AS auction_total_bids, MAX(b.value_cents) AS winner_bid,
|
|
317
|
+
date(a.finished_at) as auction_date,
|
|
318
|
+
(SELECT COUNT(*) FROM bids b2
|
|
319
|
+
WHERE b2.auction_id = #{auction_id}
|
|
320
|
+
AND b2.user_id = #{participant_id}
|
|
321
|
+
) AS winner_total_bids
|
|
322
|
+
FROM auctions a
|
|
323
|
+
LEFT JOIN bids b ON a.id = b.auction_id AND a.id = #{auction_id}
|
|
324
|
+
LEFT JOIN users u ON u.id = b.user_id AND u.id = #{participant_id}
|
|
325
|
+
LEFT JOIN (
|
|
326
|
+
SELECT auction_id, user_id, MAX(value_cents) AS value_cents
|
|
327
|
+
FROM bids
|
|
328
|
+
WHERE auction_id = #{auction_id}
|
|
329
|
+
GROUP BY auction_id, user_id
|
|
330
|
+
ORDER BY value_cents DESC
|
|
331
|
+
LIMIT 1
|
|
332
|
+
) AS w ON a.id = w.auction_id
|
|
333
|
+
WHERE a.id = #{auction_id}
|
|
334
|
+
GROUP BY a.id
|
|
335
|
+
SQL
|
|
336
|
+
|
|
337
|
+
read(sql)
|
|
257
338
|
end
|
|
258
339
|
end
|
|
259
340
|
end
|
|
@@ -23,6 +23,24 @@ module AuctionFunCore
|
|
|
23
23
|
|
|
24
24
|
struct_namespace Entities
|
|
25
25
|
auto_struct(true)
|
|
26
|
+
|
|
27
|
+
# Retrieves a list of unique user IDs who have placed bids in a specified auction.
|
|
28
|
+
# A participant in an auction is defined as a user who has placed one or more bids.
|
|
29
|
+
#
|
|
30
|
+
# @param auction_id [Integer] the ID of the auction.
|
|
31
|
+
# @return [Array<Integer>] Returns an array of unique user IDs who have participated in the auction.
|
|
32
|
+
# @raise [RuntimeError] Raises an error if the auction_id is not an integer.
|
|
33
|
+
def participants(auction_id)
|
|
34
|
+
raise "Invalid argument" unless auction_id.is_a?(Integer)
|
|
35
|
+
|
|
36
|
+
sql = <<-SQL
|
|
37
|
+
SELECT COALESCE(ARRAY_AGG(DISTINCT user_id), ARRAY[]::INT[]) AS participant_ids
|
|
38
|
+
FROM bids
|
|
39
|
+
WHERE auction_id = #{auction_id}
|
|
40
|
+
SQL
|
|
41
|
+
|
|
42
|
+
read(sql)
|
|
43
|
+
end
|
|
26
44
|
end
|
|
27
45
|
end
|
|
28
46
|
end
|
|
@@ -3,7 +3,30 @@
|
|
|
3
3
|
module AuctionFunCore
|
|
4
4
|
module Repos
|
|
5
5
|
module AuctionContext
|
|
6
|
-
#
|
|
6
|
+
# Repository for handling repository operations related to auctions.
|
|
7
|
+
#
|
|
8
|
+
# This repository provides methods to interact with auction data in the database,
|
|
9
|
+
# including creating, updating, deleting, and retrieving auctions.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# auction_repo = AuctionFunCore::Repos::AuctionContext::AuctionRepository.new
|
|
13
|
+
#
|
|
14
|
+
# # Retrieve all auctions
|
|
15
|
+
# all_auctions = auction_repo.all
|
|
16
|
+
#
|
|
17
|
+
# # Get the total number of auctions
|
|
18
|
+
# total_auctions = auction_repo.count
|
|
19
|
+
#
|
|
20
|
+
# # Find an auction by its ID
|
|
21
|
+
# auction = auction_repo.by_id(123)
|
|
22
|
+
#
|
|
23
|
+
# # Find an auction by its ID and raise an error if not found
|
|
24
|
+
# auction = auction_repo.by_id!(123)
|
|
25
|
+
#
|
|
26
|
+
# @see AuctionFunCore::Entities::Auction Struct representing auction data
|
|
27
|
+
# @see https://rom-rb.org/learn/sql/3.3/queries/
|
|
28
|
+
# @see https://api.rom-rb.org/rom-sql/ROM/SQL/Relation/Reading
|
|
29
|
+
#
|
|
7
30
|
class AuctionRepository < ROM::Repository[:auctions]
|
|
8
31
|
include Import["container"]
|
|
9
32
|
|
|
@@ -11,28 +34,34 @@ module AuctionFunCore
|
|
|
11
34
|
commands :create, update: :by_pk, delete: :by_pk
|
|
12
35
|
|
|
13
36
|
# Returns all auctions in the database.
|
|
14
|
-
# @return [Array<ROM::Struct::Auction
|
|
37
|
+
# @return [Array<ROM::Struct::Auction>]
|
|
15
38
|
def all
|
|
16
39
|
auctions.to_a
|
|
17
40
|
end
|
|
18
41
|
|
|
19
|
-
# Returns the total number of auctions in database.
|
|
20
|
-
#
|
|
42
|
+
# Returns the total number of auctions in the database.
|
|
43
|
+
#
|
|
44
|
+
# @return [Integer] Total number of auctions.
|
|
45
|
+
#
|
|
21
46
|
def count
|
|
22
47
|
auctions.count
|
|
23
48
|
end
|
|
24
49
|
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# @
|
|
50
|
+
# Retrieves an auction from the database by its primary key.
|
|
51
|
+
#
|
|
52
|
+
# @param id [Integer] The ID of the auction to retrieve.
|
|
53
|
+
# @return [ROM::Struct::Auction, nil] The retrieved auction, or nil if not found.
|
|
54
|
+
#
|
|
28
55
|
def by_id(id)
|
|
29
56
|
auctions.by_pk(id).one
|
|
30
57
|
end
|
|
31
58
|
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
# @
|
|
35
|
-
# @
|
|
59
|
+
# Retrieves an auction from the database by its primary key, raising an error if not found.
|
|
60
|
+
#
|
|
61
|
+
# @param id [Integer] The ID of the auction to retrieve.
|
|
62
|
+
# @raise [ROM::TupleCountMismatchError] if the auction is not found.
|
|
63
|
+
# @return [ROM::Struct::Auction] The retrieved auction.
|
|
64
|
+
#
|
|
36
65
|
def by_id!(id)
|
|
37
66
|
auctions.by_pk(id).one!
|
|
38
67
|
end
|
|
@@ -3,21 +3,43 @@
|
|
|
3
3
|
module AuctionFunCore
|
|
4
4
|
module Repos
|
|
5
5
|
module BidContext
|
|
6
|
-
#
|
|
6
|
+
# Repository for handling repository operations related to bids.
|
|
7
|
+
#
|
|
8
|
+
# This repository provides methods to interact with bid data in the database,
|
|
9
|
+
# including creating, updating, deleting, and retrieving bids.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# bid_repo = AuctionFunCore::Repos::BidContext::BidRepository.new
|
|
13
|
+
#
|
|
14
|
+
# # Get the total number of bids
|
|
15
|
+
# total_bids = bid_repo.count
|
|
16
|
+
#
|
|
17
|
+
# # Checks if a bid exists based on the provided conditions.
|
|
18
|
+
# bid_repo.exists?(id: 123)
|
|
19
|
+
#
|
|
20
|
+
# @see AuctionFunCore::Entities::Bid Struct representing bid data
|
|
21
|
+
# @see https://rom-rb.org/learn/sql/3.3/queries/
|
|
22
|
+
# @see https://api.rom-rb.org/rom-sql/ROM/SQL/Relation/Reading
|
|
23
|
+
#
|
|
7
24
|
class BidRepository < ROM::Repository[:bids]
|
|
8
25
|
include Import["container"]
|
|
9
26
|
|
|
10
27
|
struct_namespace Entities
|
|
11
28
|
commands :create, update: :by_pk, delete: :by_pk
|
|
12
29
|
|
|
13
|
-
# Returns the total number of bids in database.
|
|
14
|
-
#
|
|
30
|
+
# Returns the total number of bids in the database.
|
|
31
|
+
#
|
|
32
|
+
# @return [Integer] Total number of bids.
|
|
33
|
+
#
|
|
15
34
|
def count
|
|
16
35
|
bids.count
|
|
17
36
|
end
|
|
18
37
|
|
|
19
|
-
#
|
|
20
|
-
#
|
|
38
|
+
# Checks if a bid exists based on the provided conditions.
|
|
39
|
+
#
|
|
40
|
+
# @param conditions [Hash] The conditions to check (DSL Dataset).
|
|
41
|
+
# @return [Boolean] true if a bid exists that matches the conditions, otherwise false.
|
|
42
|
+
#
|
|
21
43
|
def exists?(conditions)
|
|
22
44
|
bids.exist?(conditions)
|
|
23
45
|
end
|