auction_fun_core 0.8.7 → 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 +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
@@ -3,12 +3,27 @@
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Contracts
|
5
5
|
module UserContext
|
6
|
-
#
|
6
|
+
# This class is designed to authenticate users.
|
7
|
+
# It verifies the provided login credentials against stored user data in the system.
|
8
|
+
#
|
9
|
+
# @example Authenticating a user
|
10
|
+
# contract = AuctionFunCore::Contracts::UserContext::AuthenticationContract.new
|
11
|
+
# attributes = { login: 'example_user', password: 'securePassword123' }
|
12
|
+
# result = contract.call(attributes)
|
13
|
+
# if result.success?
|
14
|
+
# puts "User authenticated successfully."
|
15
|
+
# else
|
16
|
+
# puts "Authentication failed: #{result.errors.to_h}"
|
17
|
+
# end
|
18
|
+
#
|
7
19
|
class AuthenticationContract < ApplicationContract
|
20
|
+
# Scope for internationalization (i18n) entries specific to errors in this contract.
|
8
21
|
I18N_SCOPE = "contracts.errors.custom.default"
|
9
22
|
|
23
|
+
# Repositories initialized to retrieve data for validation.
|
10
24
|
option :user_repository, default: proc { Repos::UserContext::UserRepository.new }
|
11
25
|
|
26
|
+
# Parameters specifying the required input types and fields.
|
12
27
|
params do
|
13
28
|
required(:login)
|
14
29
|
required(:password)
|
@@ -18,12 +33,11 @@ module AuctionFunCore
|
|
18
33
|
end
|
19
34
|
end
|
20
35
|
|
36
|
+
# Additional rules for validating the format of login and password.
|
21
37
|
rule(:login).validate(:login_format)
|
22
38
|
rule(:password).validate(:password_format)
|
23
39
|
|
24
|
-
#
|
25
|
-
# Searches for the user in the database from the login, and, if found,
|
26
|
-
# compares the entered password.
|
40
|
+
# Validates the presence of the user in the database and checks if the password matches.
|
27
41
|
rule do |context:|
|
28
42
|
next if (rule_error?(:login) || schema_error?(:login)) || (rule_error?(:password) || schema_error?(:password))
|
29
43
|
|
@@ -3,12 +3,27 @@
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Contracts
|
5
5
|
module UserContext
|
6
|
-
#
|
6
|
+
# This class provides validation for confirming email addresses.
|
7
|
+
# It verifies the provided email confirmation token against stored user data in the system.
|
8
|
+
#
|
9
|
+
# @example Confirming an email address
|
10
|
+
# contract = AuctionFunCore::Contracts::UserContext::EmailConfirmationContract.new
|
11
|
+
# attributes = { email_confirmation_token: 'example_token' }
|
12
|
+
# result = contract.call(attributes)
|
13
|
+
# if result.success?
|
14
|
+
# puts "Email address enabled for confirmation."
|
15
|
+
# else
|
16
|
+
# puts "Failed to confirm email address: #{result.errors.to_h}"
|
17
|
+
# end
|
18
|
+
#
|
7
19
|
class EmailConfirmationContract < ApplicationContract
|
20
|
+
# Scope for internationalization (i18n) entries specific to errors in this contract.
|
8
21
|
I18N_SCOPE = "contracts.errors.custom.default"
|
9
22
|
|
23
|
+
# Repositories initialized to retrieve data for validation.
|
10
24
|
option :user_repository, default: proc { Repos::UserContext::UserRepository.new }
|
11
25
|
|
26
|
+
# Parameters specifying the required input types and fields.
|
12
27
|
params do
|
13
28
|
required(:email_confirmation_token)
|
14
29
|
|
@@ -17,7 +32,6 @@ module AuctionFunCore
|
|
17
32
|
end
|
18
33
|
end
|
19
34
|
|
20
|
-
# Validation for email_confirmation_token.
|
21
35
|
# Searches for the user in the database from the email_confirmation_token
|
22
36
|
rule do |context:|
|
23
37
|
next if schema_error?(:email_confirmation_token)
|
@@ -29,6 +43,7 @@ module AuctionFunCore
|
|
29
43
|
key(:email_confirmation_token).failure(I18n.t("not_found", scope: I18N_SCOPE))
|
30
44
|
end
|
31
45
|
|
46
|
+
# Additional validation to check if the user account associated with the token is active.
|
32
47
|
rule do |context:|
|
33
48
|
next if context[:user].blank? || context[:user].active?
|
34
49
|
|
@@ -3,12 +3,27 @@
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Contracts
|
5
5
|
module UserContext
|
6
|
-
#
|
6
|
+
# This class provides validation for confirming phone numbers.
|
7
|
+
# It verifies the provided phone confirmation token against stored user data in the system.
|
8
|
+
#
|
9
|
+
# @example Confirming a phone number
|
10
|
+
# contract = AuctionFunCore::Contracts::UserContext::PhoneConfirmationContract.new
|
11
|
+
# attributes = { phone_confirmation_token: 'example_token' }
|
12
|
+
# result = contract.call(attributes)
|
13
|
+
# if result.success?
|
14
|
+
# puts "Phone number enabled for confirmation."
|
15
|
+
# else
|
16
|
+
# puts "Failed to confirm phone number: #{result.errors.to_h}"
|
17
|
+
# end
|
18
|
+
#
|
7
19
|
class PhoneConfirmationContract < ApplicationContract
|
20
|
+
# Scope for internationalization (i18n) entries specific to errors in this contract.
|
8
21
|
I18N_SCOPE = "contracts.errors.custom.default"
|
9
22
|
|
23
|
+
# Repositories initialized to retrieve data for validation.
|
10
24
|
option :user_repository, default: proc { Repos::UserContext::UserRepository.new }
|
11
25
|
|
26
|
+
# Parameters specifying the required input types and fields.
|
12
27
|
params do
|
13
28
|
required(:phone_confirmation_token)
|
14
29
|
|
@@ -17,7 +32,6 @@ module AuctionFunCore
|
|
17
32
|
end
|
18
33
|
end
|
19
34
|
|
20
|
-
# Validation for token_confirmation_token.
|
21
35
|
# Searches for the user in the database from the phone_confirmation_token
|
22
36
|
rule do |context:|
|
23
37
|
next if schema_error?(:phone_confirmation_token)
|
@@ -29,6 +43,7 @@ module AuctionFunCore
|
|
29
43
|
key(:phone_confirmation_token).failure(I18n.t("not_found", scope: I18N_SCOPE))
|
30
44
|
end
|
31
45
|
|
46
|
+
# Additional validation to check if the user account associated with the token is active.
|
32
47
|
rule do |context:|
|
33
48
|
next if context[:user].blank? || context[:user].active?
|
34
49
|
|
@@ -3,13 +3,33 @@
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Contracts
|
5
5
|
module UserContext
|
6
|
-
#
|
6
|
+
# This class is designed to create new users.
|
7
|
+
# It validates the parameters, ensuring their format and uniqueness.
|
8
|
+
#
|
9
|
+
# @example Registering a new staff member
|
10
|
+
# contract = AuctionFunCore::Contracts::StaffContext::RegistrationContract.new
|
11
|
+
# attributes = {
|
12
|
+
# name: 'John Doe',
|
13
|
+
# email: 'john.doe@example.com',
|
14
|
+
# phone: '1234567890'
|
15
|
+
# password: 'password',
|
16
|
+
# password_confirmation: 'password'
|
17
|
+
# }
|
18
|
+
# result = contract.call(attributes)
|
19
|
+
# if result.success?
|
20
|
+
# puts "New user registered successfully."
|
21
|
+
# else
|
22
|
+
# puts "Failed to register new user: #{result.errors.to_h}"
|
23
|
+
# end
|
24
|
+
#
|
7
25
|
class RegistrationContract < ApplicationContract
|
26
|
+
# Scope for internationalization (i18n) entries specific to errors in this contract.
|
8
27
|
I18N_SCOPE = "contracts.errors.custom.default"
|
9
28
|
|
29
|
+
# Repositories initialized to retrieve data for validation.
|
10
30
|
option :user_repository, default: proc { Repos::UserContext::UserRepository.new }
|
11
31
|
|
12
|
-
#
|
32
|
+
# Parameters specifying the required input types and fields.
|
13
33
|
params do
|
14
34
|
required(:name)
|
15
35
|
required(:email)
|
@@ -21,17 +41,17 @@ module AuctionFunCore
|
|
21
41
|
result.to_h.compact
|
22
42
|
end
|
23
43
|
|
24
|
-
#
|
44
|
+
# Normalizes and adds default values after coercion.
|
25
45
|
after(:value_coercer) do |result|
|
26
46
|
result.update(email: result[:email].strip.downcase) if result[:email]
|
27
47
|
result.update(phone: result[:phone].tr_s("^0-9", "")) if result[:phone]
|
28
48
|
end
|
29
49
|
end
|
30
50
|
|
51
|
+
# Validates the format of the user's name.
|
31
52
|
rule(:name).validate(:name_format)
|
32
53
|
|
33
|
-
#
|
34
|
-
# It must validate the format and uniqueness in the database.
|
54
|
+
# It ensures email format and checks for uniqueness in the database.
|
35
55
|
rule(:email).validate(:email_format)
|
36
56
|
rule(:email) do
|
37
57
|
# Email should be unique on database
|
@@ -40,8 +60,7 @@ module AuctionFunCore
|
|
40
60
|
end
|
41
61
|
end
|
42
62
|
|
43
|
-
#
|
44
|
-
# It must validate the format and uniqueness in the database.
|
63
|
+
# It ensures phone format and checks for uniqueness in the database.
|
45
64
|
rule(:phone).validate(:phone_format)
|
46
65
|
rule(:phone) do
|
47
66
|
if !rule_error?(:phone) && user_repository.exists?(phone: value)
|
@@ -49,7 +68,6 @@ module AuctionFunCore
|
|
49
68
|
end
|
50
69
|
end
|
51
70
|
|
52
|
-
# Validation for password.
|
53
71
|
# Check if the confirmation matches the password.
|
54
72
|
rule(:password).validate(:password_format)
|
55
73
|
rule(:password, :password_confirmation) do
|
@@ -2,22 +2,66 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Entities
|
5
|
-
|
6
|
-
# to
|
5
|
+
##
|
6
|
+
# Defines the Auction class as Entity. It appears to be a simple data structure
|
7
|
+
# class representing auction-related information.
|
7
8
|
class Auction < ROM::Struct
|
8
|
-
|
9
|
-
|
9
|
+
# Retrieves the initial bid amount for an auction as a Money object.
|
10
|
+
#
|
11
|
+
# This method creates and returns a new Money object that represents the initial bid
|
12
|
+
# amount required to start bidding in the auction. It utilizes `initial_bid_cents` and
|
13
|
+
# `initial_bid_currency` attributes to construct the Money object, ensuring that the amount
|
14
|
+
# is correctly represented in the specified currency.
|
15
|
+
#
|
16
|
+
# @return [Money] Returns a Money object representing the initial bid amount with the specified currency.
|
10
17
|
def initial_bid
|
11
18
|
Money.new(initial_bid_cents, initial_bid_currency)
|
12
19
|
end
|
13
20
|
|
21
|
+
# Retrieves the minimal bid amount for an auction as a Money object.
|
22
|
+
#
|
23
|
+
# This method creates and returns a new Money object that represents the minimal bid
|
24
|
+
# amount required to participate in the auction. It uses `minimal_bid_cents` and
|
25
|
+
# `minimal_bid_currency` attributes to construct the Money object.
|
26
|
+
#
|
27
|
+
# @return [Money] Returns a Money object representing the minimal bid amount with the appropriate currency.
|
14
28
|
def minimal_bid
|
15
29
|
Money.new(minimal_bid_cents, minimal_bid_currency)
|
16
30
|
end
|
17
31
|
|
32
|
+
# Checks if an auction has a winner.
|
33
|
+
#
|
34
|
+
# This method determines if an auction has a winner based on the presence of a `winner_id`.
|
35
|
+
# It returns true if the `winner_id` is present, indicating that the auction has concluded
|
36
|
+
# with a winning bidder.
|
37
|
+
#
|
38
|
+
# @return [Boolean] Returns `true` if there is a winner for the auction, otherwise returns `false`.
|
18
39
|
def winner?
|
19
40
|
winner_id.present?
|
20
41
|
end
|
42
|
+
|
43
|
+
# Checks if an auction has already started.
|
44
|
+
#
|
45
|
+
# This method determines if an auction has begun based on its status and by comparing
|
46
|
+
# the auction's start time (`started_at`) with the current time. An auction is considered
|
47
|
+
# started if it is no longer scheduled (i.e., its status is not "scheduled") and
|
48
|
+
# the start time (`started_at`) is equal to or before the current time.
|
49
|
+
# @return [Boolean] Returns `true` if the auction has already started, otherwise returns `false`.
|
50
|
+
def started?
|
51
|
+
status != "scheduled" && Time.current > started_at
|
52
|
+
end
|
53
|
+
|
54
|
+
# Checks if an auction has not started yet.
|
55
|
+
#
|
56
|
+
# This method verifies if an auction is still in the "scheduled" status and whether
|
57
|
+
# its start time (`started_at`) is still in the future compared to the current time.
|
58
|
+
# The auction is considered not started if it is scheduled and the start time
|
59
|
+
# has not yet been reached.
|
60
|
+
#
|
61
|
+
# @return [Boolean] Returns `true` if the auction has not started yet, otherwise returns `false`.
|
62
|
+
def not_started?
|
63
|
+
status == "scheduled" && Time.current <= started_at
|
64
|
+
end
|
21
65
|
end
|
22
66
|
end
|
23
67
|
end
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Entities
|
5
|
-
|
6
|
-
# to
|
5
|
+
##
|
6
|
+
# Defines the Bid class as Entity. It appears to be a simple data structure
|
7
|
+
# class representing bid-related information.
|
7
8
|
class Bid < ROM::Struct
|
8
9
|
end
|
9
10
|
end
|
@@ -2,17 +2,30 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Entities
|
5
|
-
|
6
|
-
# to
|
5
|
+
##
|
6
|
+
# Defines the Staff class as Entity. It appears to be a simple data structure
|
7
|
+
# class representing staff-related information.
|
7
8
|
class Staff < ROM::Struct
|
9
|
+
##
|
10
|
+
# Checks if the staff is active.
|
11
|
+
#
|
12
|
+
# @return [Boolean] True if the staff is active, otherwise false.
|
8
13
|
def active?
|
9
14
|
active
|
10
15
|
end
|
11
16
|
|
17
|
+
##
|
18
|
+
# Checks if the staff is inactive.
|
19
|
+
#
|
20
|
+
# @return [Boolean] True if the staff is inactive, otherwise false.
|
12
21
|
def inactive?
|
13
22
|
!active
|
14
23
|
end
|
15
24
|
|
25
|
+
##
|
26
|
+
# Returns staff information excluding password digest.
|
27
|
+
#
|
28
|
+
# @return [Hash] Staff information.
|
16
29
|
def info
|
17
30
|
attributes.except(:password_digest)
|
18
31
|
end
|
@@ -2,33 +2,62 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Entities
|
5
|
-
|
6
|
-
# to
|
5
|
+
##
|
6
|
+
# Defines the User class as Entity. It appears to be a simple data structure
|
7
|
+
# class representing user-related information.
|
7
8
|
class User < ROM::Struct
|
9
|
+
##
|
10
|
+
# Checks if the user is active.
|
11
|
+
#
|
12
|
+
# @return [Boolean] True if the user is active, otherwise false.
|
8
13
|
def active?
|
9
14
|
active
|
10
15
|
end
|
11
16
|
|
17
|
+
##
|
18
|
+
# Checks if the user is inactive.
|
19
|
+
#
|
20
|
+
# @return [Boolean] True if the user is inactive, otherwise false.
|
12
21
|
def inactive?
|
13
22
|
!active
|
14
23
|
end
|
15
24
|
|
25
|
+
##
|
26
|
+
# Checks if the user has been confirmed.
|
27
|
+
#
|
28
|
+
# @return [Boolean] True if the user is confirmed, otherwise false.
|
16
29
|
def confirmed?
|
17
30
|
confirmed_at.present?
|
18
31
|
end
|
19
32
|
|
33
|
+
##
|
34
|
+
# Checks if the user's email has been confirmed.
|
35
|
+
#
|
36
|
+
# @return [Boolean] True if the email is confirmed, otherwise false.
|
20
37
|
def email_confirmed?
|
21
38
|
email_confirmation_at.present?
|
22
39
|
end
|
23
40
|
|
41
|
+
##
|
42
|
+
# Checks if the user's phone has been confirmed.
|
43
|
+
#
|
44
|
+
# @return [Boolean] True if the phone is confirmed, otherwise false.
|
24
45
|
def phone_confirmed?
|
25
46
|
phone_confirmation_at.present?
|
26
47
|
end
|
27
48
|
|
49
|
+
##
|
50
|
+
# Returns user information excluding password digest.
|
51
|
+
#
|
52
|
+
# @return [Hash] User information.
|
28
53
|
def info
|
29
54
|
attributes.except(:password_digest)
|
30
55
|
end
|
31
56
|
|
57
|
+
##
|
58
|
+
# Returns the user's balance as a Money object.
|
59
|
+
#
|
60
|
+
# @return [Money] User's balance.
|
32
61
|
def balance
|
33
62
|
Money.new(balance_cents, balance_currency)
|
34
63
|
end
|
@@ -2,23 +2,29 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Events
|
5
|
-
|
5
|
+
##
|
6
|
+
# Represents the main application class for registering business events in the system.
|
7
|
+
#
|
8
|
+
# This class includes Dry::Events::Publisher[:app] to enable event publishing functionality.
|
6
9
|
# @see https://dry-rb.org/gems/dry-events/main/
|
7
10
|
class App
|
8
|
-
# @!parser include Dry::Events::Publisher[:app]
|
9
11
|
include Dry::Events::Publisher[:app]
|
10
12
|
|
13
|
+
# Registers events related to auctions.
|
11
14
|
register_event("auctions.created")
|
12
15
|
register_event("auctions.started")
|
13
16
|
register_event("auctions.finished")
|
14
17
|
register_event("auctions.paused")
|
15
18
|
register_event("auctions.unpaused")
|
16
19
|
|
20
|
+
# Registers events related to bids.
|
17
21
|
register_event("bids.created")
|
18
22
|
|
23
|
+
# Registers events related to staffs.
|
19
24
|
register_event("staffs.authentication")
|
20
25
|
register_event("staffs.registration")
|
21
26
|
|
27
|
+
# Registers events related to users.
|
22
28
|
register_event("users.authentication")
|
23
29
|
register_event("users.registration")
|
24
30
|
register_event("users.confirmation")
|
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
module AuctionFunCore
|
4
4
|
module Events
|
5
|
-
|
5
|
+
##
|
6
|
+
# Represents a class that listens to business events and performs actions accordingly.
|
7
|
+
#
|
8
|
+
# This class defines methods to handle various events related to auctions, bids, staff, and users.
|
6
9
|
# @see https://dry-rb.org/gems/dry-events/main/#event-listeners
|
7
10
|
class Listener
|
8
11
|
# Listener for to *auctions.created* event.
|
@@ -36,15 +39,15 @@ module AuctionFunCore
|
|
36
39
|
end
|
37
40
|
|
38
41
|
# Listener for to *bids.created* event.
|
39
|
-
# @param event [
|
42
|
+
# @param event [ROM::Struct::Bid] Auction ID
|
40
43
|
def on_bids_created(bid)
|
41
44
|
logger("Create bid with: #{bid.to_h}")
|
42
45
|
end
|
43
46
|
|
44
|
-
# Listener for
|
45
|
-
# @param attributes [Hash] Authentication attributes
|
46
|
-
# @option staff_id [Integer] Staff ID
|
47
|
-
# @option time [DateTime] Authentication time
|
47
|
+
# Listener for the *staffs.authentication* event.
|
48
|
+
# @param attributes [Hash] Authentication attributes.
|
49
|
+
# @option attributes staff_id [Integer] Staff ID.
|
50
|
+
# @option attributes time [DateTime] Authentication time.
|
48
51
|
def on_staffs_authentication(attributes)
|
49
52
|
logger("Staff #{attributes[:staff_id]} authenticated on: #{attributes[:time].iso8601}")
|
50
53
|
end
|
@@ -61,26 +64,26 @@ module AuctionFunCore
|
|
61
64
|
logger("New registered user: #{user.to_h}")
|
62
65
|
end
|
63
66
|
|
64
|
-
# Listener for
|
65
|
-
# @param attributes [Hash] Authentication attributes
|
66
|
-
# @option user_id [Integer] User ID
|
67
|
-
# @option time [DateTime] Authentication time
|
67
|
+
# Listener for the *users.authentication* event.
|
68
|
+
# @param attributes [Hash] Authentication attributes.
|
69
|
+
# @option attributes user_id [Integer] User ID.
|
70
|
+
# @option attributes time [DateTime] Authentication time.
|
68
71
|
def on_users_authentication(attributes)
|
69
72
|
logger("User #{attributes[:user_id]} authenticated on: #{attributes[:time].iso8601}")
|
70
73
|
end
|
71
74
|
|
72
|
-
# Listener for
|
73
|
-
# @param attributes [Hash] Confirmation attributes
|
74
|
-
# @option user_id [Integer] User ID
|
75
|
-
# @option time [DateTime] Authentication time
|
75
|
+
# Listener for the *users.confirmation* event.
|
76
|
+
# @param attributes [Hash] Confirmation attributes.
|
77
|
+
# @option user_id [Integer] User ID.
|
78
|
+
# @option time [DateTime] Authentication time.
|
76
79
|
def on_users_confirmation(attributes)
|
77
80
|
logger("User #{attributes[:user_id]} confirmed at: #{attributes[:time].iso8601}")
|
78
81
|
end
|
79
82
|
|
80
83
|
private
|
81
84
|
|
82
|
-
#
|
83
|
-
# @param message [String]
|
85
|
+
# Appends a message to the system log.
|
86
|
+
# @param message [String] The message.
|
84
87
|
def logger(message)
|
85
88
|
Application[:logger].info(message)
|
86
89
|
end
|
@@ -10,6 +10,7 @@ module AuctionFunCore
|
|
10
10
|
include Import["repos.auction_context.auction_repository"]
|
11
11
|
include Import["contracts.auction_context.create_contract"]
|
12
12
|
include Import["workers.operations.auction_context.processor.start_operation_job"]
|
13
|
+
include Import["workers.operations.auction_context.pre_auction.auction_start_reminder_operation_job"]
|
13
14
|
|
14
15
|
# @todo Add custom doc
|
15
16
|
def self.call(attributes, &block)
|
@@ -27,6 +28,7 @@ module AuctionFunCore
|
|
27
28
|
auction_repository.transaction do |_t|
|
28
29
|
@auction = yield persist(values)
|
29
30
|
yield scheduled_start_auction(@auction)
|
31
|
+
yield schedule_auction_notification(@auction)
|
30
32
|
yield publish_auctions_created(@auction)
|
31
33
|
end
|
32
34
|
|
@@ -63,15 +65,6 @@ module AuctionFunCore
|
|
63
65
|
Success(auction_repository.create(result))
|
64
66
|
end
|
65
67
|
|
66
|
-
# Triggers the publication of event *auctions.created*.
|
67
|
-
# @param auction [Hash] Auction persisted attributes
|
68
|
-
# @return [Dry::Monads::Result::Success]
|
69
|
-
def publish_auctions_created(auction)
|
70
|
-
Application[:event].publish("auctions.created", auction.to_h)
|
71
|
-
|
72
|
-
Success()
|
73
|
-
end
|
74
|
-
|
75
68
|
# Calls the background job class that will schedule the start of the auction.
|
76
69
|
# Added a small delay to perform operations (such as sending broadcasts and/or other operations).
|
77
70
|
# @param auction [ROM::Struct::Auction]
|
@@ -81,6 +74,29 @@ module AuctionFunCore
|
|
81
74
|
|
82
75
|
Success(start_operation_job.class.perform_at(perform_at, auction.id))
|
83
76
|
end
|
77
|
+
|
78
|
+
# Schedules a notification to be sent to users one hour before the auction starts.
|
79
|
+
# The scheduling is only done if the start of the auction is more than one hour ahead of the current time,
|
80
|
+
# ensuring that there is sufficient time for the notification to be sent.
|
81
|
+
#
|
82
|
+
# @param auction [ROM::Struct::Auction]
|
83
|
+
# @return [String] sidekiq jid
|
84
|
+
def schedule_auction_notification(auction)
|
85
|
+
perform_time = auction.started_at - 1.hour
|
86
|
+
|
87
|
+
return Success() if perform_time <= Time.current
|
88
|
+
|
89
|
+
Success(auction_start_reminder_operation_job.class.perform_at(perform_time, auction.id))
|
90
|
+
end
|
91
|
+
|
92
|
+
# Triggers the publication of event *auctions.created*.
|
93
|
+
# @param auction [ROM::Struct::Auction]
|
94
|
+
# @return [Dry::Monads::Result::Success]
|
95
|
+
def publish_auctions_created(auction)
|
96
|
+
Application[:event].publish("auctions.created", auction.to_h)
|
97
|
+
|
98
|
+
Success()
|
99
|
+
end
|
84
100
|
end
|
85
101
|
end
|
86
102
|
end
|
@@ -5,13 +5,29 @@ module AuctionFunCore
|
|
5
5
|
module AuctionContext
|
6
6
|
module PostAuction
|
7
7
|
##
|
8
|
-
# Operation class for
|
8
|
+
# Operation class for managing participants in auctions.
|
9
9
|
#
|
10
10
|
class ParticipantOperation < AuctionFunCore::Operations::Base
|
11
11
|
include Import["repos.user_context.user_repository"]
|
12
12
|
include Import["contracts.auction_context.post_auction.participant_contract"]
|
13
13
|
include Import["workers.services.mail.auction_context.post_auction.participant_mailer_job"]
|
14
14
|
|
15
|
+
##
|
16
|
+
# Executes the participant operation with the provided attributes.
|
17
|
+
#
|
18
|
+
# @param attributes [Hash] The attributes for the winner operation.
|
19
|
+
# @option attributes auction_id [Integer] The ID of the auction.
|
20
|
+
# @option attributes participant_id [Integer] The participating user ID.
|
21
|
+
# @yield [Dry::Matcher::Evaluator] The block to handle the result of the operation.
|
22
|
+
# @return [Dry::Matcher::Evaluator] The result of the operation.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# attributes = { auction_id: 123, participant_id: 123 }
|
26
|
+
#
|
27
|
+
# AuctionFunCore::Operations::AuctionContext::PostAuction::ParticipantOperation.call(attributes) do |result|
|
28
|
+
# result.success { |auction| puts "Participation operation completed successfully! #{auction.to_h}" }
|
29
|
+
# result.failure { |failure| puts "Failed auction participation operation: #{failure.errors.to_h}"}
|
30
|
+
# end
|
15
31
|
def self.call(attributes, &block)
|
16
32
|
operation = new.call(attributes)
|
17
33
|
|
@@ -20,8 +36,12 @@ module AuctionFunCore
|
|
20
36
|
Dry::Matcher::ResultMatcher.call(operation, &block)
|
21
37
|
end
|
22
38
|
|
23
|
-
##
|
24
|
-
#
|
39
|
+
##
|
40
|
+
# Executes the participant operation.
|
41
|
+
#
|
42
|
+
# @param attributes [Hash] The attributes for the participant operation.
|
43
|
+
# @return [Dry::Monads::Result] The result of the operation.
|
44
|
+
#
|
25
45
|
def call(attributes)
|
26
46
|
auction, participant = yield validate_contract(attributes)
|
27
47
|
|
@@ -34,6 +54,12 @@ module AuctionFunCore
|
|
34
54
|
|
35
55
|
private
|
36
56
|
|
57
|
+
##
|
58
|
+
# Validates the contract with the provided attributes.
|
59
|
+
#
|
60
|
+
# @param attributes [Hash] The attributes to validate.
|
61
|
+
# @return [Dry::Monads::Result] The result of the validation.
|
62
|
+
#
|
37
63
|
def validate_contract(attributes)
|
38
64
|
contract = participant_contract.call(attributes)
|
39
65
|
|
@@ -42,6 +68,13 @@ module AuctionFunCore
|
|
42
68
|
Success([contract.context[:auction], contract.context[:participant]])
|
43
69
|
end
|
44
70
|
|
71
|
+
##
|
72
|
+
# Sends participant email with auction statistics and payment instructions.
|
73
|
+
#
|
74
|
+
# @param auction_id [Integer] The ID of the auction.
|
75
|
+
# @param participant_id [Integer] The ID of the participant.
|
76
|
+
# @return [Dry::Monads::Result] The result of sending the email.
|
77
|
+
#
|
45
78
|
def send_participant_email_with_statistics_and_payment_instructions(auction_id, participant_id)
|
46
79
|
Success(participant_mailer_job.class.perform_async(auction_id, participant_id))
|
47
80
|
end
|