diff --git a/apps/hellgate/src/hg_invoice_payment.erl b/apps/hellgate/src/hg_invoice_payment.erl index a15f442..73c53f5 100644 --- a/apps/hellgate/src/hg_invoice_payment.erl +++ b/apps/hellgate/src/hg_invoice_payment.erl @@ -2214,10 +2214,12 @@ process_failure({payment, Step} = Activity, Events, Action, Failure, St, _Refund _ = maybe_notify_fault_detector(Activity, TargetType, OperationStatus, St), process_fatal_payment_failure(Target, Events, Action, Failure, St) end; - -process_failure({refund_new, ID}, [], Action, Failure, _St, _RefundSt) -> - {next, {[?refund_ev(ID, ?refund_rollback_started(Failure))], hg_machine_action:set_timeout(0, Action)}}; -process_failure({refund_session, ID}, Events, Action, Failure, St, _RefundSt) -> +process_failure({refund_new, ID}, Events, Action, Failure, St, RefundSt) -> + _Clocks = rollback_refund_cashflow(RefundSt, St), + {done, {Events ++ [?refund_ev(ID, ?refund_status_changed(?refund_failed(Failure)))], Action}}; +% process_failure({refund_new, ID}, [], Action, Failure, _St, _RefundSt) -> +% {next, {[?refund_ev(ID, ?refund_rollback_started(Failure))], hg_machine_action:set_timeout(0, Action)}}; +process_failure({refund_session, ID}, Events, Action, Failure, St, RefundSt) -> Target = ?refunded(), case check_retry_possibility(Target, Failure, St) of {retry, Timeout} -> @@ -2226,10 +2228,16 @@ process_failure({refund_session, ID}, Events, Action, Failure, St, _RefundSt) -> Events1 = [?refund_ev(ID, E) || E <- SessionEvents], {next, {Events ++ Events1, SessionAction}}; fatal -> + _Clocks = rollback_refund_cashflow(RefundSt, St), Events1 = [ - ?refund_ev(ID, ?refund_rollback_started(Failure)) + ?refund_ev(ID, ?refund_status_changed(?refund_failed(Failure))) ], - {next, {Events ++ Events1, hg_machine_action:set_timeout(0, Action)}} + {done, {Events ++ Events1, Action}} + % fatal -> + % Events1 = [ + % ?refund_ev(ID, ?refund_rollback_started(Failure)) + % ], + % {next, {Events ++ Events1, hg_machine_action:set_timeout(0, Action)}} end. choose_fd_operation_status_for_failure({failure, Failure}) -> @@ -2292,9 +2300,15 @@ process_fatal_payment_failure(?cancelled(), _Events, _Action, Failure, _St) -> error({invalid_cancel_failure, Failure}); process_fatal_payment_failure(?captured(), _Events, _Action, Failure, _St) -> error({invalid_capture_failure, Failure}); -process_fatal_payment_failure(?processed(), Events, Action, Failure, _St) -> - RollbackStarted = [?payment_rollback_started(Failure)], - {next, {Events ++ RollbackStarted, hg_machine_action:set_timeout(0, Action)}}. +% process_fatal_payment_failure(?processed(), [], Action, Failure, _St) -> +% {next, {[?payment_rollback_started(Failure)], hg_machine_action:set_timeout(0, Action)}}; +% process_fatal_payment_failure(?processed(), Events, Action, Failure, _St) -> +% RollbackStarted = [?payment_rollback_started(Failure)], +% {next, {Events ++ RollbackStarted, hg_machine_action:set_timeout(0, Action)}}; +process_fatal_payment_failure(_Target, Events, Action, Failure, St) -> + _Clocks = rollback_payment_cashflow(St), + PaymentFailed = [?payment_status_changed(?failed(Failure))], + {done, {Events ++ PaymentFailed, Action}}. retry_session(Action, Target, Timeout) -> NewEvents = start_session(Target), @@ -2831,7 +2845,12 @@ merge_change(?payment_status_changed(Status), #st{activity = {adjustment_pending } }; merge_change(Change = ?payment_rollback_started(Failure), St, Opts) -> - _ = validate_transition([{payment, processing_session}], Change, St, Opts), + _ = validate_transition([{payment, S} || S <- [ + risk_scoring, + routing, + processing_session, + processing_failure + ]], Change, St, Opts), St#st{ failure = Failure, activity = {payment, processing_failure}, @@ -2841,6 +2860,7 @@ merge_change(Change = ?payment_status_changed({failed, _} = Status), #st{payment _ = validate_transition([{payment, S} || S <- [ risk_scoring, routing, + processing_session, processing_failure ]], Change, St, Opts), St#st{ @@ -2943,7 +2963,7 @@ merge_change(Change = ?refund_ev(ID, Event), St, Opts) -> _ = validate_transition([{refund_session, ID}, {refund_new, ID}], Change, St, Opts), St#st{activity = {refund_failure, ID}}; ?refund_status_changed(?refund_failed(_)) -> - _ = validate_transition([{refund_failure, ID}], Change, St, Opts), + _ = validate_transition([{refund_session, ID}, {refund_new, ID}, {refund_failure, ID}], Change, St, Opts), St; _ -> _ = validate_transition([{refund_session, ID}], Change, St, Opts), diff --git a/apps/hellgate/test/hg_invoice_tests_SUITE.erl b/apps/hellgate/test/hg_invoice_tests_SUITE.erl index b60c6c7..a14e6a7 100644 --- a/apps/hellgate/test/hg_invoice_tests_SUITE.erl +++ b/apps/hellgate/test/hg_invoice_tests_SUITE.erl @@ -947,7 +947,6 @@ processing_deadline_reached_test(C) -> PaymentParams = PaymentParams0#payproc_InvoicePaymentParams{processing_deadline = Deadline}, PaymentID = start_payment(InvoiceID, PaymentParams, Client), PaymentID = await_sessions_restarts(PaymentID, ?processed(), InvoiceID, Client, 0), - [?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure}))] = next_event(InvoiceID, Client), [?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure})))] = next_event(InvoiceID, Client), ok = payproc_errors:match( 'PaymentFailure', @@ -1252,11 +1251,8 @@ payment_suspend_timeout_failure(C) -> ] = next_event(InvoiceID, Client), PaymentID = await_payment_session_started(InvoiceID, PaymentID, Client, ?processed()), [ - ?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_failed({failure, Failure})))), - ?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure})) - ] = next_event(InvoiceID, Client), - [ - ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) + ?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_failed({failure, _Failure})))), + ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, _Failure}))) ] = next_event(InvoiceID, Client). -spec payment_w_wallet_success(config()) -> _ | no_return(). @@ -3448,9 +3444,6 @@ payment_refund_success(C) -> Refund0 = #domain_InvoicePaymentRefund{id = RefundID0} = hg_client_invoicing:refund_payment(InvoiceID, PaymentID, RefundParams, Client), PaymentID = refund_payment(InvoiceID, PaymentID, RefundID0, Refund0, Client), - [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_rollback_started(Failure))) - ] = next_event(InvoiceID, Client), [ ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(Failure)))) ] = next_event(InvoiceID, Client), @@ -3500,9 +3493,6 @@ payment_refund_failure(C) -> Refund0 = #domain_InvoicePaymentRefund{id = RefundID0} = hg_client_invoicing:refund_payment(InvoiceID, PaymentID, RefundParams, Client), PaymentID = refund_payment(InvoiceID, PaymentID, RefundID0, Refund0, Client), - [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_rollback_started(NoFunds))) - ] = next_event(InvoiceID, Client), [ ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(NoFunds)))) ] = next_event(InvoiceID, Client), @@ -3519,9 +3509,6 @@ payment_refund_failure(C) -> PaymentID = await_refund_session_started(InvoiceID, PaymentID, RefundID, Client), [ ?payment_ev(PaymentID, ?refund_ev(ID, ?session_ev(?refunded(), ?session_finished(?session_failed(Failure))))), - ?payment_ev(PaymentID, ?refund_ev(ID, ?refund_rollback_started(Failure))) - ] = next_event(InvoiceID, Client), - [ ?payment_ev(PaymentID, ?refund_ev(ID, ?refund_status_changed(?refund_failed(Failure)))) ] = next_event(InvoiceID, Client), #domain_InvoicePaymentRefund{status = ?refund_failed(Failure)} = @@ -3544,17 +3531,14 @@ deadline_doesnt_affect_payment_refund(C) -> PaymentID = await_payment_capture(InvoiceID, PaymentID, Client), timer:sleep(ProcessingDeadline), % not enough funds on the merchant account - NoFunds = {failure, payproc_errors:construct('RefundFailure', + Failure = {failure, payproc_errors:construct('RefundFailure', {terms_violated, {insufficient_merchant_funds, #payprocerr_GeneralFailure{}}} )}, Refund0 = #domain_InvoicePaymentRefund{id = RefundID0} = hg_client_invoicing:refund_payment(InvoiceID, PaymentID, RefundParams, Client), PaymentID = refund_payment(InvoiceID, PaymentID, RefundID0, Refund0, Client), [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_rollback_started(NoFunds))) - ] = next_event(InvoiceID, Client), - [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(NoFunds)))) + ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(Failure)))) ] = next_event(InvoiceID, Client), % top up merchant account InvoiceID2 = start_invoice(ShopID, <<"rubberduck">>, make_due_date(10), 42000, C), @@ -3594,7 +3578,7 @@ payment_manual_refund(C) -> }, PaymentID = await_payment_capture(InvoiceID, PaymentID, Client), % not enough funds on the merchant account - NoFunds = {failure, payproc_errors:construct('RefundFailure', + Failure = {failure, payproc_errors:construct('RefundFailure', {terms_violated, {insufficient_merchant_funds, #payprocerr_GeneralFailure{}}} )}, Refund0 = #domain_InvoicePaymentRefund{id = RefundID0} = @@ -3603,10 +3587,7 @@ payment_manual_refund(C) -> ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_created(Refund0, _, TrxInfo))) ] = next_event(InvoiceID, Client), [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_rollback_started(NoFunds))) - ] = next_event(InvoiceID, Client), - [ - ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(NoFunds)))) + ?payment_ev(PaymentID, ?refund_ev(RefundID0, ?refund_status_changed(?refund_failed(Failure)))) ] = next_event(InvoiceID, Client), % top up merchant account InvoiceID2 = start_invoice(ShopID, <<"rubberduck">>, make_due_date(10), 42000, C), @@ -4490,9 +4471,6 @@ payment_with_offsite_preauth_failed(C) -> PaymentID, ?session_ev(?processed(), ?session_finished(?session_failed({failure, Failure}))) ), - ?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure})) - ] = next_event(InvoiceID, 8000, Client), - [ ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) ] = next_event(InvoiceID, 8000, Client), ok = payproc_errors:match('PaymentFailure', Failure, fun({authorization_failed, _}) -> ok end), @@ -4527,6 +4505,7 @@ repair_fail_pre_processing_succeeded(C) -> timeout = next_event(InvoiceID, 2000, Client), ok = repair_invoice_with_scenario(InvoiceID, fail_pre_processing, Client), + [ ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, _Failure}))) ] = next_event(InvoiceID, Client). @@ -4579,9 +4558,6 @@ repair_fail_session_succeeded(C) -> [ ?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_failed({failure, Failure})))), - ?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure})) - ] = next_event(InvoiceID, Client), - [ ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) ] = next_event(InvoiceID, Client). @@ -4605,6 +4581,7 @@ repair_fail_session_on_pre_processing(C) -> repair_invoice_with_scenario(InvoiceID, fail_session, Client) ), ok = repair_invoice_with_scenario(InvoiceID, fail_pre_processing, Client), + [ ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, _Failure}))) ] = next_event(InvoiceID, Client). @@ -4657,9 +4634,6 @@ repair_complex_succeeded_second(C) -> [ ?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_failed({failure, Failure})))), - ?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure})) - ] = next_event(InvoiceID, Client), - [ ?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) ] = next_event(InvoiceID, Client). @@ -5193,9 +5167,6 @@ await_payment_process_failure(InvoiceID, PaymentID, Client, Restarts, Target) -> PaymentID, ?session_ev(Target, ?session_finished(?session_failed(Failure))) ), - ?payment_ev(PaymentID, ?payment_rollback_started(Failure)) - ] = next_event(InvoiceID, Client), - [ ?payment_ev(PaymentID, ?payment_status_changed(?failed(Failure))) ] = next_event(InvoiceID, Client), {failed, PaymentID, Failure}.