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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +2 -0
  3. data/CHANGELOG.md +23 -0
  4. data/Procfile +1 -0
  5. data/README.md +34 -32
  6. data/Rakefile +1 -1
  7. data/i18n/en-US/contracts/contracts.en-US.yml +3 -0
  8. data/i18n/en-US/mail/application.en-US.yml +7 -0
  9. data/i18n/en-US/mail/auction_context/pre_auction/auction_start_reminder.en-US.yml +11 -0
  10. data/i18n/pt-BR/contracts/contracts.pt-BR.yml +3 -0
  11. data/i18n/pt-BR/mail/application.pt-BR.yml +7 -0
  12. data/i18n/pt-BR/mail/auction_context/pre_auction/auction_start_reminder.pt-BR.yml +11 -0
  13. data/lib/auction_fun_core/business/configuration.rb +31 -0
  14. data/lib/auction_fun_core/business/token_generator.rb +19 -1
  15. data/lib/auction_fun_core/contracts/application_contract.rb +9 -1
  16. data/lib/auction_fun_core/contracts/auction_context/create_contract.rb +35 -20
  17. data/lib/auction_fun_core/contracts/auction_context/post_auction/participant_contract.rb +23 -1
  18. data/lib/auction_fun_core/contracts/auction_context/post_auction/winner_contract.rb +22 -1
  19. data/lib/auction_fun_core/contracts/auction_context/pre_auction/auction_start_reminder_contract.rb +48 -0
  20. data/lib/auction_fun_core/contracts/auction_context/processor/finish/closed_contract.rb +19 -7
  21. data/lib/auction_fun_core/contracts/auction_context/processor/finish/penny_contract.rb +19 -7
  22. data/lib/auction_fun_core/contracts/auction_context/processor/finish/standard_contract.rb +19 -7
  23. data/lib/auction_fun_core/contracts/auction_context/processor/pause_contract.rb +16 -4
  24. data/lib/auction_fun_core/contracts/auction_context/processor/start_contract.rb +17 -5
  25. data/lib/auction_fun_core/contracts/auction_context/processor/unpause_contract.rb +16 -4
  26. data/lib/auction_fun_core/contracts/bid_context/create_bid_closed_contract.rb +20 -11
  27. data/lib/auction_fun_core/contracts/bid_context/create_bid_penny_contract.rb +18 -9
  28. data/lib/auction_fun_core/contracts/bid_context/create_bid_standard_contract.rb +19 -10
  29. data/lib/auction_fun_core/contracts/staff_context/authentication_contract.rb +18 -4
  30. data/lib/auction_fun_core/contracts/staff_context/registration_contract.rb +20 -8
  31. data/lib/auction_fun_core/contracts/user_context/authentication_contract.rb +18 -4
  32. data/lib/auction_fun_core/contracts/user_context/email_confirmation_contract.rb +17 -2
  33. data/lib/auction_fun_core/contracts/user_context/phone_confirmation_contract.rb +17 -2
  34. data/lib/auction_fun_core/contracts/user_context/registration_contract.rb +26 -8
  35. data/lib/auction_fun_core/entities/auction.rb +48 -4
  36. data/lib/auction_fun_core/entities/bid.rb +3 -2
  37. data/lib/auction_fun_core/entities/staff.rb +15 -2
  38. data/lib/auction_fun_core/entities/user.rb +31 -2
  39. data/lib/auction_fun_core/events/app.rb +8 -2
  40. data/lib/auction_fun_core/events/listener.rb +19 -16
  41. data/lib/auction_fun_core/operations/auction_context/create_operation.rb +25 -9
  42. data/lib/auction_fun_core/operations/auction_context/post_auction/participant_operation.rb +36 -3
  43. data/lib/auction_fun_core/operations/auction_context/post_auction/winner_operation.rb +36 -2
  44. data/lib/auction_fun_core/operations/auction_context/pre_auction/auction_start_reminder_operation.rb +96 -0
  45. data/lib/auction_fun_core/operations/auction_context/processor/finish/closed_operation.rb +82 -10
  46. data/lib/auction_fun_core/operations/auction_context/processor/finish/penny_operation.rb +81 -10
  47. data/lib/auction_fun_core/operations/auction_context/processor/finish/standard_operation.rb +81 -12
  48. data/lib/auction_fun_core/operations/auction_context/processor/pause_operation.rb +36 -1
  49. data/lib/auction_fun_core/operations/auction_context/processor/unpause_operation.rb +36 -1
  50. data/lib/auction_fun_core/relations/auctions.rb +178 -97
  51. data/lib/auction_fun_core/relations/bids.rb +18 -0
  52. data/lib/auction_fun_core/repos/auction_context/auction_repository.rb +40 -11
  53. data/lib/auction_fun_core/repos/bid_context/bid_repository.rb +27 -5
  54. data/lib/auction_fun_core/repos/staff_context/staff_repository.rb +63 -21
  55. data/lib/auction_fun_core/repos/user_context/user_repository.rb +69 -25
  56. data/lib/auction_fun_core/services/mail/auction_context/post_auction/participant_mailer.rb +7 -1
  57. data/lib/auction_fun_core/services/mail/auction_context/post_auction/winner_mailer.rb +7 -1
  58. data/lib/auction_fun_core/services/mail/auction_context/pre_auction/auction_start_reminder_mailer.rb +35 -0
  59. data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/participant.html.erb +1 -1
  60. data/lib/auction_fun_core/services/mail/templates/auction_context/post_auction/winner.html.erb +1 -1
  61. data/lib/auction_fun_core/services/mail/templates/auction_context/pre_auction/auction_start_reminder.html.erb +192 -0
  62. data/lib/auction_fun_core/services/mail/user_context/registration_mailer.rb +6 -0
  63. data/lib/auction_fun_core/version.rb +1 -1
  64. data/lib/auction_fun_core/workers/application_job.rb +10 -0
  65. data/lib/auction_fun_core/workers/operations/auction_context/post_auction/participant_operation_job.rb +7 -2
  66. data/lib/auction_fun_core/workers/operations/auction_context/post_auction/winner_operation_job.rb +6 -2
  67. data/lib/auction_fun_core/workers/operations/auction_context/pre_auction/auction_start_reminder_operation_job.rb +44 -0
  68. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/closed_operation_job.rb +6 -3
  69. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/penny_operation_job.rb +6 -3
  70. data/lib/auction_fun_core/workers/operations/auction_context/processor/finish/standard_operation_job.rb +6 -2
  71. data/lib/auction_fun_core/workers/operations/auction_context/processor/start_operation_job.rb +6 -3
  72. data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/participant_mailer_job.rb +12 -7
  73. data/lib/auction_fun_core/workers/services/mail/auction_context/post_auction/winner_mailer_job.rb +11 -5
  74. data/lib/auction_fun_core/workers/services/mail/auction_context/pre_auction/auction_start_reminder_mailer_job.rb +48 -0
  75. data/lib/auction_fun_core/workers/services/mail/user_context/registration_mailer_job.rb +8 -6
  76. data/system/providers/background_job.rb +6 -0
  77. metadata +10 -2
@@ -3,12 +3,27 @@
3
3
  module AuctionFunCore
4
4
  module Contracts
5
5
  module UserContext
6
- # Contract class to authenticate users.
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
- # Validation for login.
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
- # Contract class responsible for validating the confirmation token for email.
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
- # Contract class responsible for validating the confirmation token for phone number.
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
- # Contract class to create new users.
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
- # @param [Hash] opts Sets an allowed list of parameters, as well as some initial validations.
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
- # Normalize and add default values
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
- # Validation for email.
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
- # Validation for phone.
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
- # Auction Relations class. This return simple objects with attribute readers
6
- # to represent data in your auction.
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
- INQUIRER_ATTRIBUTES = Relations::Auctions::STATUSES.values.freeze
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
- # Bid Relations class. This return simple objects with attribute readers
6
- # to represent data in your bid.
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
- # Staff Relations class. This return simple objects with attribute readers
6
- # to represent data in your staff.
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
- # User Relations class. This return simple objects with attribute readers
6
- # to represent data in your user.
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
- # Event class to register business events on system.
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
- # Event class that can listen business events.
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 [Integer] Auction ID
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 to *staffs.authentication* event.
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 to *users.authentication* event.
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 to *users.confirmation* event.
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
- # Append message to system log.
83
- # @param message [String] the message
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 finish auctions.
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
- ## @todo Add more actions
24
- # Send email to participant with auction statistics.
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