我有一个循环,可为订单下的任何购买创建退款。
订单可以有多笔付款(如果用户升级运输,在初次付款后将商品添加到购物车并重新提交等),这在电子商务中并不是很麻烦,但在这种情况下是必需的。
我有这个循环:
orders_payments = Payment.where()
orders_payments.each do |btp|
transaction = gateway.transaction.find("#{btp.transaction_token}")
if transaction.status == "submitted_for_settlement"
void = gateway.transaction.void("#{btp.transaction_token}")
if void.success?
format.html { redirect_to user_orders_path, notice: 'Order refund was successfully refunded.' }
else
format.html { redirect user_orders_path, notice: 'Order refund unsuccessful.' }
end
elsif transaction.status == "settled"
refund = gateway.transaction.refund("#{btp.transaction_token}")
if refund.success?
format.html { redirect_to user_orders_path, notice: 'Order refund was successfully refunded.' }
else
format.html { redirect user_orders_path, notice: 'Order refund unsuccessful.' }
end
end
end
当然,由于重定向,这不起作用。但是除了不创建重定向之外,而且重要的是我有一个带有状态消息的重定向...如何在创建循环后检查无效状态或退款的状态。
我希望能够检查哪些有效,哪些无效。
关于如何做到这一点的任何想法?
答案 0 :(得分:2)
您可以使用多个循环将数据分为几类,而不是一个循环。
迭代的第一步是检索transaction
对象。也可以使用map
:
transactions = orders_payments.map do |btp|
gateway.transaction.find("#{btp.transaction_token}")
end
下一步是if
语句,该语句根据数据的状态将其分为两组。您可以使用select
来构造这两个列表:
submitted = transactions.select do |transaction|
transaction.status == "submitted_for_settlement"
end
settled = transactions.select do |transaction|
transaction.status == "settled"
end
下一步是处理两个列表,并跟踪成功或失败的列表。听起来像到此结束时,您想要每个事务组的“成功”和“失败”列表,剩下4个列表。 partition
是此用例的好方法:
successful_submitted, failed_submitted = submitted.partition do |transaction|
gateway.transaction.void("#{btp.transaction_token}").success?
end
successful_settled, failed_settled = settled.partition do |transaction|
gateway.transaction.refund("#{btp.transaction_token}").success?
end
答案 1 :(得分:1)
您可以使用each_with_object
存储状态。在这里,我将它们存储在transaction_token
的哈希中。
请注意,我使用的是find_each
而不是each
,以避免立即将所有记录拖入内存。
transaction_statuses = orders_payments.find_each.each_with_object({}) do |btp,status|
transaction = gateway.transaction.find("#{btp.transaction_token}")
status[btp.transaction_token] = case
when transaction.status == "submitted_for_settlement"
{ voided: gateway.transaction.void("#{btp.transaction_token}") }
when transaction.status == "settled"
{ refunded: gateway.transaction.refund("#{btp.transaction_token}") }
end
end
然后稍后对它们进行处理。
transaction_statuses.each do |token,status|
case
when status[:voided]
case
when status[:voided].success?
puts "Order #{token} was successfully voided."
else
puts "Order #{token} void failed."
end
when status[:refunded]
case
when status[:refunded].success?
puts "Order #{token} was successfully refunded."
else
puts "Order #{token} refund failed."
end
end
end
答案 2 :(得分:1)
如果您是因为遇到相同或相似的问题而来这里,在阅读此书之前,我建议您阅读max pleaner和Schwern关于该问题的答案。
以下方法可以工作,但可能是我做自己想做的事情的一个非常初学者的方法。
我创建了一个空白数组,然后使用flash.keep
将消息存储在其中,然后在循环完成所有消息(无论退款成功还是退款)后重定向。
orders_payments = Payment.where()
messages = []
orders_payments.each do |btp|
transaction = gateway.transaction.find("#{btp.transaction_token}")
if transaction.status == "submitted_for_settlement"
void = gateway.transaction.void("#{btp.transaction_token}")
if void.success?
messages << "Refund Successful message"
else
messages << "Refund unSuccessful message"
end
elsif transaction.status == "settled"
refund = gateway.transaction.refund("#{btp.transaction_token}")
if refund.success?
messages << "Refund successful message"
else
messages << "Refund unSuccessful message"
end
end
end
flash.keep[:notice] = messages.join if messages.any?
respond_to do |format|
format.html { redirect_to route }
end
...