From ce8bc0669954b14c293817fc9668c5f6b58ab775 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Sat, 22 May 2021 08:38:30 +0200 Subject: [PATCH] Prepare voucher usage --- payment/const.py | 11 ++++++++ payment/voucher/__init__.py | 0 payment/voucher/helpers.py | 18 ++++++++++++ payment/voucher/models.py | 55 +++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 5 files changed, 85 insertions(+) create mode 100644 payment/const.py create mode 100644 payment/voucher/__init__.py create mode 100644 payment/voucher/helpers.py create mode 100644 payment/voucher/models.py diff --git a/payment/const.py b/payment/const.py new file mode 100644 index 0000000..e6d4e61 --- /dev/null +++ b/payment/const.py @@ -0,0 +1,11 @@ +# Payment Status Constants + +PAYMENT_STATUS_INITIATED = -100 + +PAYMENT_STATUS_AUTHORIZED = -1 +PAYMENT_STATUS_SUCCESS = 0 + +PAYMENT_STATUS_FAILED = 1 +PAYMENT_STATUS_REFUNDED = 2 + +PAYMENT_STATUS_CANCELLED = 100 \ No newline at end of file diff --git a/payment/voucher/__init__.py b/payment/voucher/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/payment/voucher/helpers.py b/payment/voucher/helpers.py new file mode 100644 index 0000000..ec79f43 --- /dev/null +++ b/payment/voucher/helpers.py @@ -0,0 +1,18 @@ +from dbsettings.functions import getValue + +from random import SystemRandom + +import fast_luhn + +def generate_voucher_code(prefix=getValue("payment.voucher.prefix", "9011"), length=getValue("payment.voucher.length", 16)): + if length <= len(str(prefix)): + raise ValueError("Voucher code length must be longer than its prefix!") + + length_randpart = length - len(str(prefix)) - 1 + + base_code = prefix + + for i in range(length_randpart): + base_code += str(SystemRandom().randint(0, 9)) + + return fast_luhn.complete(base_code) \ No newline at end of file diff --git a/payment/voucher/models.py b/payment/voucher/models.py new file mode 100644 index 0000000..f117e45 --- /dev/null +++ b/payment/voucher/models.py @@ -0,0 +1,55 @@ +from django.db import models +from django.contrib.auth import get_user_model + +from .helpers import generate_voucher_code + +from payment.const import PAYMENT_STATUS_SUCCESS, PAYMENT_STATUS_FAILED, PAYMENT_STATUS_REFUNDED +from clients.models import ClientProfile + +class Voucher(models.Model): + code = models.IntegerField(default=generate_voucher_code) + value = models.DecimalField(max_digits=10, decimal_places=2) + created_at = models.DateTimeField(auto_now_add=True) + + @property + def is_active(self): + try: + self.voucheractivation + return True + except VoucherActivation.DoesNotExist: + return False + +class VoucherActivation(models.Model): + voucher = models.OneToOneField(Voucher, models.PROTECT) + user = models.ForeignKey(get_user_model(), models.PROTECT) + activated_at = models.DateTimeField(auto_now_add=True) + data = models.CharField(max_length=256) + +class VoucherApplication(models.Model): + voucher = models.OneToOneField(Voucher, models.PROTECT) + client = models.ForeignKey(get_user_model(), models.PROTECT) + applied_at = models.DateTimeField(auto_now_add=True) + +class VoucherInvoicePayment(InvoicePayment): + success = models.BooleanField(default=True) + + @property + def gateway(self): + return "Voucher" + + @classmethod + def initiate(cls, invoice, amount=None): + amount = amount or (invoice.balance * -1) + + payment = cls.objects.create(invoice=invoice, amount=amount, gateway_id=uuid.uuid4()) + + if invoice.user.balance <= 0: + payment.success = False + payment.save() + + invoice.finalize() + return reverse_lazy("payment:status", args=[payment.uuid]) + + @property + def status(self): + return PAYMENT_STATUS_SUCCESS if self.success else PAYMENT_STATUS_FAILED \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8a9a05d..70befe0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,5 @@ googlemaps Babel staticmap django-mathfilters +fast-luhn git+https://kumig.it/kumisystems/PyInvoice \ No newline at end of file