Skip to content

Commit

Permalink
Replace the subscription logic with a wallet logic as per jazzband#21…
Browse files Browse the repository at this point in the history
  • Loading branch information
radekholy24 committed May 30, 2024
1 parent 4f9df42 commit c423186
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 64 deletions.
12 changes: 12 additions & 0 deletions payments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ class FraudStatus:
]


class WalletStatus:
PENDING = "pending"
ACTIVE = "active"
ERASED = "erased"

CHOICES = [
(PENDING, pgettext_lazy("wallet status", "Pending")),
(ACTIVE, pgettext_lazy("wallet status", "Active")),
(ERASED, pgettext_lazy("wallet status", "Erased")),
]


class RedirectNeeded(Exception):
pass

Expand Down
12 changes: 4 additions & 8 deletions payments/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,25 +143,21 @@ def get_return_url(
return url + "?" + qs
return url

def autocomplete_with_subscription(self, payment):
def autocomplete_with_wallet(self, payment):
"""
Complete the payment with subscription
Complete the payment with wallet
If the provider uses workflow such that the payments are initiated from
implementer's side.
The users of django-payments will create a payment and call
Payment.autocomplete_with_subscription() right before the subscription end.
Payment.autocomplete_with_wallet().
Throws RedirectNeeded if there is problem with the payment
that needs to be solved by user.
"""
raise NotImplementedError

def cancel_subscription(self, subscription):
"""
Cancel subscription
Used by providers, that use provider initiated cancellation workflow
"""
def erase_wallet(self, wallet):
raise NotImplementedError

def capture(self, payment, amount=None):
Expand Down
71 changes: 15 additions & 56 deletions payments/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import enum
import json
from typing import Iterable
from uuid import uuid4
Expand All @@ -13,6 +12,7 @@
from . import FraudStatus
from . import PaymentStatus
from . import PurchasedItem
from . import WalletStatus
from .core import provider_factory


Expand Down Expand Up @@ -40,58 +40,29 @@ def __setattr__(self, key, value):
return None


class BaseSubscription(models.Model):
class BaseWallet(models.Model):
token = models.CharField(
_("subscription token/id"),
help_text=_("Token/id used to identify subscription by provider"),
_("wallet token/id"),
help_text=_("Token/id used to identify wallet by provider"),
max_length=255,
default=None,
null=True,
blank=True,
)
payment_provider = models.CharField(
_("payment provider"),
help_text=_("Provider variant, that will be used for payment renewal"),
max_length=255,
default=None,
null=True,
blank=True,
status = models.CharField(
max_length=10, choices=WalletStatus.CHOICES, default=WalletStatus.PENDING
)
subscribtion_data = models.JSONField(
_("subscription data"),
help_text=_("Provider-specific data associated with subscription"),
extra_data = models.JSONField(
_("extra data"),
help_text=_("Provider-specific data associated with wallet"),
default=dict,
)

class TimeUnit(enum.Enum):
year = "year"
month = "month"
day = "day"

def set_recurrence(self, token: str, **kwargs):
"""
Sets token and other values associated with subscription recurrence
Kwargs can contain provider-specific values
"""
self.token = token
self.subscribtion_data = kwargs

def get_period(self) -> int:
raise NotImplementedError

def get_unit(self) -> TimeUnit:
raise NotImplementedError

def cancel(self):
def payment_completed(self, payment):
"""
Cancel the subscription by provider
Used by providers, that use provider initiated subscription workflow
Implementer is responsible for cancelling the subscription model
Raises PaymentError if the cancellation didn't pass through
Concrete implementation specific logic called whenever a payment is completed
using this wallet.
"""
provider = provider_factory(self.variant)
provider.cancel_subscription(self)

class Meta:
abstract = True
Expand Down Expand Up @@ -251,30 +222,18 @@ def get_payment_url(self) -> str:
"""
raise NotImplementedError

def get_subscription(self) -> BaseSubscription | None:
"""
Returns subscription object associated with this payment
or None if the payment is not recurring
"""
return None

def is_recurring(self) -> bool:
return self.get_subscription() is not None

def autocomplete_with_subscription(self):
def autocomplete_with_wallet(self):
"""
Complete the payment with subscription
Complete the payment with wallet
If the provider uses workflow such that the payments are initiated from
implementer's side.
Call this function right before the subscription end to
make a new subscription payment.
Throws RedirectNeeded if there is problem with the payment
that needs to be solved by user
"""
provider = provider_factory(self.variant)
provider.autocomplete_with_subscription(self)
provider.autocomplete_with_wallet(self)

def capture(self, amount=None):
"""Capture a pre-authorized payment.
Expand Down

0 comments on commit c423186

Please sign in to comment.