2020-04-01 12:51:18 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Provides methods to manage wallets
|
2016-07-05 13:20:25 +02:00
|
|
|
class WalletService
|
|
|
|
def initialize(user: nil, wallet: nil)
|
|
|
|
@user = user
|
|
|
|
@wallet = wallet
|
|
|
|
end
|
|
|
|
|
2016-07-20 13:03:46 +02:00
|
|
|
## credit an amount to wallet, if credit success then return a wallet transaction and notify to admin
|
2016-07-05 13:20:25 +02:00
|
|
|
def credit(amount)
|
2022-10-11 11:41:44 +02:00
|
|
|
transaction = nil
|
2016-07-20 13:03:46 +02:00
|
|
|
ActiveRecord::Base.transaction do
|
2022-10-11 11:41:44 +02:00
|
|
|
if @wallet&.credit(amount)
|
2020-04-01 12:51:18 +02:00
|
|
|
transaction = WalletTransaction.new(
|
2022-10-11 11:41:44 +02:00
|
|
|
invoicing_profile: @user&.invoicing_profile,
|
2020-04-01 12:51:18 +02:00
|
|
|
wallet: @wallet,
|
|
|
|
transaction_type: 'credit',
|
|
|
|
amount: amount
|
|
|
|
)
|
2022-10-11 11:41:44 +02:00
|
|
|
raise ActiveRecord::Rollback unless transaction.save
|
|
|
|
|
|
|
|
NotificationCenter.call type: 'notify_user_wallet_is_credited',
|
|
|
|
receiver: @wallet&.user,
|
|
|
|
attached_object: transaction
|
|
|
|
NotificationCenter.call type: 'notify_admin_user_wallet_is_credited',
|
|
|
|
receiver: User.admins_and_managers,
|
|
|
|
attached_object: transaction
|
2016-07-20 13:03:46 +02:00
|
|
|
end
|
2016-07-05 13:20:25 +02:00
|
|
|
end
|
2022-10-11 11:41:44 +02:00
|
|
|
transaction
|
2016-07-07 15:57:06 +02:00
|
|
|
end
|
|
|
|
|
2016-07-20 13:03:46 +02:00
|
|
|
## debit an amount to wallet, if debit success then return a wallet transaction
|
2021-05-27 13:43:54 +02:00
|
|
|
def debit(amount)
|
2022-10-11 11:41:44 +02:00
|
|
|
transaction = nil
|
2016-07-20 13:03:46 +02:00
|
|
|
ActiveRecord::Base.transaction do
|
2022-10-11 11:41:44 +02:00
|
|
|
if @wallet&.debit(amount)
|
2019-06-03 16:00:09 +02:00
|
|
|
transaction = WalletTransaction.new(
|
|
|
|
invoicing_profile: @user&.invoicing_profile,
|
|
|
|
wallet: @wallet,
|
|
|
|
transaction_type: 'debit',
|
2021-05-27 13:43:54 +02:00
|
|
|
amount: amount
|
2019-06-03 16:00:09 +02:00
|
|
|
)
|
|
|
|
|
2022-10-11 11:41:44 +02:00
|
|
|
raise ActiveRecord::Rollback unless transaction.save
|
2016-07-20 13:03:46 +02:00
|
|
|
end
|
2016-07-07 15:57:06 +02:00
|
|
|
end
|
2022-10-11 11:41:44 +02:00
|
|
|
transaction
|
2016-12-12 14:20:26 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
## create a refund invoice associated with the given wallet transaction
|
|
|
|
def create_avoir(wallet_transaction, avoir_date, description)
|
|
|
|
avoir = Avoir.new
|
|
|
|
avoir.type = 'Avoir'
|
|
|
|
avoir.avoir_date = avoir_date
|
|
|
|
avoir.created_at = avoir_date
|
|
|
|
avoir.description = description
|
2019-09-17 14:48:06 +02:00
|
|
|
avoir.payment_method = 'wallet'
|
2016-12-12 14:20:26 +01:00
|
|
|
avoir.subscription_to_expire = false
|
2020-04-01 17:58:32 +02:00
|
|
|
avoir.invoicing_profile_id = wallet_transaction.wallet.user.invoicing_profile.id
|
2020-04-01 12:51:18 +02:00
|
|
|
avoir.statistic_profile_id = wallet_transaction.wallet.user.statistic_profile.id
|
2016-12-12 14:20:26 +01:00
|
|
|
avoir.total = wallet_transaction.amount * 100.0
|
2016-12-13 15:05:40 +01:00
|
|
|
|
|
|
|
ii = InvoiceItem.new
|
|
|
|
ii.amount = wallet_transaction.amount * 100.0
|
|
|
|
ii.description = I18n.t('invoices.wallet_credit')
|
2021-05-27 15:58:55 +02:00
|
|
|
ii.object = wallet_transaction
|
2021-05-28 17:34:20 +02:00
|
|
|
ii.main = true
|
2021-08-05 18:56:12 +02:00
|
|
|
|
|
|
|
avoir.invoice_items.push(ii)
|
|
|
|
avoir.save!
|
2016-07-05 13:20:25 +02:00
|
|
|
end
|
2020-12-21 16:12:34 +01:00
|
|
|
|
|
|
|
##
|
|
|
|
# Compute the amount decreased from the user's wallet, if applicable
|
2022-08-26 10:46:30 +02:00
|
|
|
# @param payment {Invoice|PaymentSchedule|Order}
|
2020-12-21 16:12:34 +01:00
|
|
|
# @param user {User} the customer
|
|
|
|
##
|
2022-09-13 12:36:18 +02:00
|
|
|
def self.wallet_amount_debit(payment, user)
|
2021-04-26 11:40:26 +02:00
|
|
|
total = if payment.is_a? PaymentSchedule
|
2020-12-30 12:19:33 +01:00
|
|
|
payment.payment_schedule_items.first.amount
|
|
|
|
else
|
|
|
|
payment.total
|
|
|
|
end
|
2022-09-13 12:36:18 +02:00
|
|
|
total = CouponService.new.apply(total, payment.coupon, user.id) if payment.coupon
|
2020-12-21 16:12:34 +01:00
|
|
|
|
|
|
|
wallet_amount = (user.wallet.amount * 100).to_i
|
|
|
|
|
|
|
|
wallet_amount >= total ? total : wallet_amount
|
|
|
|
end
|
2021-05-31 11:52:53 +02:00
|
|
|
|
|
|
|
##
|
2022-08-26 10:46:30 +02:00
|
|
|
# Subtract the amount of the payment document (Invoice|PaymentSchedule|Order) from the customer's wallet
|
2021-10-06 17:09:35 +02:00
|
|
|
# @param transaction, if false: the wallet is not debited, the transaction is only simulated on the payment document
|
2021-05-31 11:52:53 +02:00
|
|
|
##
|
2021-09-08 18:57:10 +02:00
|
|
|
def self.debit_user_wallet(payment, user, transaction: true)
|
2021-05-31 11:52:53 +02:00
|
|
|
wallet_amount = WalletService.wallet_amount_debit(payment, user)
|
|
|
|
return unless wallet_amount.present? && wallet_amount != 0
|
|
|
|
|
|
|
|
amount = wallet_amount / 100.0
|
2021-09-08 18:57:10 +02:00
|
|
|
if transaction
|
|
|
|
wallet_transaction = WalletService.new(user: user, wallet: user.wallet).debit(amount)
|
|
|
|
# wallet debit success
|
|
|
|
raise DebitWalletError unless wallet_transaction
|
2021-05-31 11:52:53 +02:00
|
|
|
|
2022-08-26 11:19:09 +02:00
|
|
|
payment.set_wallet_transaction(wallet_amount, wallet_transaction.id)
|
2021-09-08 18:57:10 +02:00
|
|
|
else
|
2022-08-26 11:19:09 +02:00
|
|
|
payment.set_wallet_transaction(wallet_amount, nil)
|
2021-09-08 18:57:10 +02:00
|
|
|
end
|
2021-05-31 11:52:53 +02:00
|
|
|
end
|
2016-07-05 13:20:25 +02:00
|
|
|
end
|