From 7e378e5b548732667ad0091eb31f96e910d9b9c9 Mon Sep 17 00:00:00 2001 From: Haydar Ghasemi Date: Sat, 14 Feb 2026 15:24:46 +0330 Subject: [PATCH] FIX(wallet): add cancel state and add success to rollback init states add cancel state and add success to rollback init states --- apps/wallet/constans.py | 1 + .../migrations/0018_alter_transaction_state.py | 18 ++++++++++++++++++ apps/wallet/models.py | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 apps/wallet/migrations/0018_alter_transaction_state.py diff --git a/apps/wallet/constans.py b/apps/wallet/constans.py index 014b3e6..b0bdaa8 100644 --- a/apps/wallet/constans.py +++ b/apps/wallet/constans.py @@ -11,6 +11,7 @@ class StateChoices(IntegerChoices): FAILED = 6 , _('failed') EXPECTED_FAILURE = 7 , _('expected_failure') # no exact data available but guessed to be failed ROLLED_BACK = 8 , _('ROLLED_BACK') + CANCELED = 9, _('CANCELED') class TypeChoices(IntegerChoices): diff --git a/apps/wallet/migrations/0018_alter_transaction_state.py b/apps/wallet/migrations/0018_alter_transaction_state.py new file mode 100644 index 0000000..cc38b11 --- /dev/null +++ b/apps/wallet/migrations/0018_alter_transaction_state.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2026-02-14 11:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wallet', '0017_transaction_reference_alter_transaction_state_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='transaction', + name='state', + field=models.IntegerField(choices=[(1, 'created'), (2, 'delayed'), (3, 'pending'), (4, 'incomplete'), (5, 'success'), (6, 'failed'), (7, 'expected_failure'), (8, 'ROLLED_BACK'), (9, 'CANCELED')], default=1), + ), + ] diff --git a/apps/wallet/models.py b/apps/wallet/models.py index 2e8d565..f92ebc3 100755 --- a/apps/wallet/models.py +++ b/apps/wallet/models.py @@ -356,7 +356,7 @@ class Transaction(BaseModel): ) return self - def rollback(self): + def cancel(self): if self.state not in [StateChoices.PENDING, StateChoices.DELAYED, StateChoices.INCOMPLETE]: raise APIException('this transaction is not pending') @@ -364,6 +364,19 @@ class Transaction(BaseModel): self.rollback_withdraw_to_payer_balance() self.change_state( [StateChoices.PENDING, StateChoices.DELAYED, StateChoices.INCOMPLETE], + StateChoices.CANCELED, + error_message=_('TRANSACTION_STATE_NOT_SUITABLE_FOR_CANCELING') + ) + return self + + def rollback(self): + if self.state not in [StateChoices.PENDING, StateChoices.SUCCESS, StateChoices.DELAYED, StateChoices.INCOMPLETE]: + raise APIException('this transaction is not pending') + + with transaction.atomic(): + self.rollback_withdraw_to_payer_balance() + self.change_state( + [StateChoices.PENDING, StateChoices.SUCCESS, StateChoices.DELAYED, StateChoices.INCOMPLETE], StateChoices.ROLLED_BACK, error_message=_('TRANSACTION_STATE_NOT_SUITABLE_FOR_ROLLBACK') )