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
|
@@ -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
|