From 8297d54cdccfd0a63ffa285c4ec93496bfecb197 Mon Sep 17 00:00:00 2001 From: Shavkatjon Odamboyev <153182519+Shavkatjon-O@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:51:56 +0500 Subject: [PATCH] feat: cards models --- apps/cards/migrations/0001_initial.py | 58 +++++++++++++++++++ apps/cards/models.py | 82 ++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 apps/cards/migrations/0001_initial.py diff --git a/apps/cards/migrations/0001_initial.py b/apps/cards/migrations/0001_initial.py new file mode 100644 index 0000000..d8e86c4 --- /dev/null +++ b/apps/cards/migrations/0001_initial.py @@ -0,0 +1,58 @@ +# Generated by Django 5.0.7 on 2024-09-12 06:51 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('clients', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Card', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('card_number', models.CharField(max_length=16, unique=True)), + ('card_type', models.CharField(choices=[('DEBIT', 'Debit'), ('CREDIT', 'Credit'), ('PREPAID', 'Prepaid'), ('VIRTUAL', 'Virtual'), ('CORPORATE', 'Corporate')], max_length=16)), + ('currency', models.CharField(choices=[('USD', 'US Dollar'), ('UZS', 'Uzbekistani Som'), ('EUR', 'Euro')], default='UZS', max_length=3)), + ('balance', models.DecimalField(decimal_places=2, default=0.0, max_digits=12)), + ('status', models.CharField(choices=[('ACTIVE', 'Active'), ('BLOCKED', 'Blocked'), ('EXPIRED', 'Expired'), ('PENDING_ACTIVATION', 'Pending Activation'), ('REPLACED', 'Replaced'), ('CLOSED', 'Closed')], default='PENDING_ACTIVATION', max_length=32)), + ('expiration_date', models.DateField()), + ('approved_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='approved_cards', to=settings.AUTH_USER_MODEL)), + ('client', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cards', to='clients.client')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_cards', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Card', + 'verbose_name_plural': 'Cards', + 'ordering': ['-created_at'], + }, + ), + migrations.CreateModel( + name='CardTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('transaction_amount', models.DecimalField(decimal_places=2, max_digits=12)), + ('transaction_date', models.DateField(auto_now_add=True)), + ('transaction_type', models.CharField(max_length=50)), + ('merchant_details', models.CharField(blank=True, max_length=256, null=True)), + ('card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transactions', to='cards.card')), + ], + options={ + 'verbose_name': 'Card Transaction', + 'verbose_name_plural': 'Card Transactions', + 'ordering': ['-transaction_date'], + }, + ), + ] diff --git a/apps/cards/models.py b/apps/cards/models.py index 71a8362..7960350 100644 --- a/apps/cards/models.py +++ b/apps/cards/models.py @@ -1,3 +1,83 @@ from django.db import models +from apps.common.models import BaseModel +from apps.clients.models import Client +from apps.users.models import User -# Create your models here. + +class CardStatusChoices(models.TextChoices): + ACTIVE = "ACTIVE", "Active" + BLOCKED = "BLOCKED", "Blocked" + EXPIRED = "EXPIRED", "Expired" + PENDING_ACTIVATION = "PENDING_ACTIVATION", "Pending Activation" + REPLACED = "REPLACED", "Replaced" + CLOSED = "CLOSED", "Closed" + + +class CardTypeChoices(models.TextChoices): + DEBIT = "DEBIT", "Debit" + CREDIT = "CREDIT", "Credit" + PREPAID = "PREPAID", "Prepaid" + VIRTUAL = "VIRTUAL", "Virtual" + CORPORATE = "CORPORATE", "Corporate" + + +class CurrencyChoices(models.TextChoices): + USD = "USD", "US Dollar" + UZS = "UZS", "Uzbekistani Som" + EUR = "EUR", "Euro" + + +class Card(BaseModel): + client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name="cards") + card_number = models.CharField(max_length=16, unique=True) + card_type = models.CharField(max_length=16, choices=CardTypeChoices.choices) + currency = models.CharField( + max_length=3, choices=CurrencyChoices.choices, default=CurrencyChoices.UZS + ) + balance = models.DecimalField(max_digits=12, decimal_places=2, default=0.00) + status = models.CharField( + max_length=32, + choices=CardStatusChoices.choices, + default=CardStatusChoices.PENDING_ACTIVATION, + ) + expiration_date = models.DateField() + created_by = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="created_cards" + ) + approved_by = models.ForeignKey( + User, + on_delete=models.CASCADE, + related_name="approved_cards", + blank=True, + null=True, + ) + + def __str__(self): + return ( + f"Card {self.card_number} - {self.client} - {self.balance} {self.currency}" + ) + + class Meta: + verbose_name = "Card" + verbose_name_plural = "Cards" + ordering = ["-created_at"] + + +class CardTransaction(BaseModel): + card = models.ForeignKey( + Card, on_delete=models.CASCADE, related_name="transactions" + ) + transaction_amount = models.DecimalField(max_digits=12, decimal_places=2) + transaction_date = models.DateField(auto_now_add=True) + transaction_type = models.CharField( + max_length=50 + ) # e.g., Purchase, Withdrawal, Deposit + merchant_details = models.CharField(max_length=256, blank=True, null=True) + + def __str__(self): + return f"Transaction {self.id} for Card {self.card.card_number} on {self.transaction_date}" + + class Meta: + verbose_name = "Card Transaction" + verbose_name_plural = "Card Transactions" + ordering = ["-transaction_date"]