24/7 Cloud Banking Suite

Share on LinkedIn
Share on X
Share on Facebook
Share on WhatsApp
Share on Telegram
Share via Email
Copy Link

For full experience in demo - deposit, withdraw and check financial reports

A secure banking management system built with Django, featuring:

  • Custom user authentication
  • Account management
  • Transaction processing
  • Balance tracking
  • Role-based access control

Technology Stack:

  • Frontend: Django Templates
  • Backend: Django 4.2
  • Database: Supabase PostgreSQL
  • Deployment: Vercel
  • Auth: Django Allauth (Custom Implementation)
Article image
graph TD
    A[Client] --> B[Vercel Edge Network]
    B --> C[Django Application]
    C --> D[Supabase Database]
    C --> E[Redis Cache]
    D --> F[(PostgreSQL Tables)]
    C --> G[Static Files]
    H[Admin User] --> C
accounts/models.py
1from django.contrib.auth.models import AbstractUser
2from django.db import models
3
4class CustomUser(AbstractUser):
5    # Remove username field
6    username = None
7    email = models.EmailField(unique=True)
8    
9    # Additional fields
10    phone_number = models.CharField(max_length=20)
11    date_of_birth = models.DateField()
12    is_verified = models.BooleanField(default=False)
13    
14    USERNAME_FIELD = 'email'
15    REQUIRED_FIELDS = ['phone_number', 'date_of_birth']
16    
17    def __str__(self):
18        return self.email
Article image
1sequenceDiagram
2    participant User
3    participant Frontend
4    participant Backend
5    participant Supabase
6    
7    User->>Frontend: Access Login Page
8    Frontend->>Backend: GET /accounts/login/
9    Backend-->>Frontend: Login Form
10    User->>Frontend: Submit Credentials
11    Frontend->>Backend: POST /accounts/login/
12    Backend->>Supabase: Verify Credentials
13    Supabase-->>Backend: User Data
14    alt Valid Credentials
15        Backend->>Backend: Create Session
16        Backend-->>Frontend: Redirect to Dashboard
17    else Invalid Credentials
18        Backend-->>Frontend: Error Message
19    end
  1. User Registration Endpoint:
accounts/views.py
# accounts/views.py
from django.views.generic import CreateView
from .forms import CustomUserCreationForm

class SignUpView(CreateView):
    form_class = CustomUserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'registration/signup.html'
  1. Registration Steps:
/accounts/signup/
POST /accounts/signup/
Content-Type: application/x-www-form-urlencoded

email=user@example.com&
password1=securePassword123&
password2=securePassword123&
phone_number=+254712345678&
date_of_birth=1990-01-01
  1. Verification Workflow:
    • Email verification sent via Celery task
    • Account activation required before login
    • JWT token generation for API access

Reset Flow:

accounts/urls.py
1# accounts/urls.py
2from django.urls import path
3from django.contrib.auth import views as auth_views
4
5urlpatterns = [
6    path('password_reset/', auth_views.PasswordResetView.as_view(
7        template_name='registration/password_reset.html',
8        email_template_name='registration/password_reset_email.html',
9        subject_template_name='registration/password_reset_subject.txt'
10    ), name='password_reset'),
11    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(
12        template_name='registration/password_reset_done.html'
13    ), name='password_reset_done'),
14    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(
15        template_name='registration/password_reset_confirm.html'
16    ), name='password_reset_confirm'),
17    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(
18        template_name='registration/password_reset_complete.html'
19    ), name='password_reset_complete'),
20]
core/settings.py
# core/settings.py
DATABASES = {
    'default': dj_database_url.config(
        default=os.environ.get('DATABASE_URL'),
        engine='django.db.backends.postgresql',
        conn_max_age=600,
        conn_health_checks=True,
        ssl_require=True
    )
}
1-- accounts_customuser
2CREATE TABLE accounts_customuser (
3    id SERIAL PRIMARY KEY,
4    password VARCHAR(128) NOT NULL,
5    last_login TIMESTAMP WITH TIME ZONE,
6    is_superuser BOOLEAN NOT NULL,
7    email VARCHAR(254) UNIQUE NOT NULL,
8    phone_number VARCHAR(20) NOT NULL,
9    date_of_birth DATE NOT NULL,
10    is_verified BOOLEAN NOT NULL,
11    ...
12);
13
14-- accounts_account
15CREATE TABLE accounts_account (
16    id SERIAL PRIMARY KEY,
17    account_type VARCHAR(20) NOT NULL,
18    account_number VARCHAR(20) UNIQUE NOT NULL,
19    balance NUMERIC(12,2) NOT NULL,
20    created_at TIMESTAMP WITH TIME ZONE NOT NULL,
21    user_id INTEGER REFERENCES accounts_customuser(id)
22);

Entity Relationship Diagram (ERD)

Article image
1classDiagram
2    class accounts_customuser {
3        +id: SERIAL (PK)
4        +password: VARCHAR(128)
5        +last_login: TIMESTAMPTZ
6        +is_superuser: BOOLEAN
7        +email: VARCHAR(254) UNIQUE
8        +phone_number: VARCHAR(20)
9        +date_of_birth: DATE
10        +is_verified: BOOLEAN
11        +created_at: TIMESTAMPTZ
12        +updated_at: TIMESTAMPTZ
13    }
14    
15    class accounts_account {
16        +id: SERIAL (PK)
17        +account_type: VARCHAR(20)
18        +account_number: VARCHAR(20) UNIQUE
19        +balance: NUMERIC(12,2)
20        +created_at: TIMESTAMPTZ
21        +user_id: INT (FK → accounts_customuser)
22    }
23    
24    class accounts_transaction {
25        +id: SERIAL (PK)
26        +transaction_type: VARCHAR(20)
27        +amount: NUMERIC(10,2)
28        +timestamp: TIMESTAMPTZ
29        +description: TEXT
30        +account_id: INT (FK → accounts_account)
31    }
32    
33    accounts_customuser "1" --> "many" accounts_account : has
34    accounts_account "1" --> "many" accounts_transaction : contains
  • User → Account Relationship
Article image
flowchart LR
    A[CustomUser] --> B[Account]
    style A fill:#f9f,stroke:#333
    style B fill:#ccf,stroke:#333
    B --> C[Transaction]
    style C fill:#cff,stroke:#333
  • Transaction Lifecycle
Article image
1journey
2    title Transaction Flow
3    section Initiation
4      User Authentication: 5: User
5      Account Verification: 5: System
6    section Processing
7      Balance Check: 4: System
8      Transaction Execution: 3: System
9    section Completion
10      Update Balance: 5: System
11      Record Transaction: 5: System

Account Creation SQL Equivalent

1INSERT INTO accounts_account (
2    account_type,
3    account_number,
4    balance,
5    created_at,
6    user_id
7) VALUES (
8    'SAVINGS',
9    'ACC-123456789',
10    0.00,
11    NOW(),
12    1
13);

Transaction Recording Example

1BEGIN;
2UPDATE accounts_account 
3SET balance = balance + 100.00
4WHERE id = 1;
5
6INSERT INTO accounts_transaction (
7    transaction_type,
8    amount,
9    timestamp,
10    account_id
11) VALUES (
12    'DEPOSIT',
13    100.00,
14    NOW(),
15    1
16);
17COMMIT;
Article image
accounts/api/views.py
1# accounts/api/views.py
2from rest_framework.viewsets import ModelViewSet
3from .serializers import AccountSerializer
4
5class AccountViewSet(ModelViewSet):
6    queryset = Account.objects.all()
7    serializer_class = AccountSerializer
8    permission_classes = [IsAuthenticated]
9
10    def get_queryset(self):
11        return self.request.user.account_set.all()
vercel.json
1// vercel.json
2{
3  "builds": [
4    {
5      "src": "core/wsgi.py",
6      "use": "@vercel/python",
7      "config": {
8        "maxLambdaSize": "15mb",
9        "runtime": "python3.9"
10      }
11    }
12  ],
13  "routes": [
14    {
15      "src": "/static/(.*)",
16      "dest": "/static/$1"
17    },
18    {
19      "src": "/media/(.*)",
20      "dest": "/media/$1"
21    },
22    {
23      "src": "/(.*)",
24      "dest": "core/wsgi.py"
25    }
26  ]
27}
  • Local Setup:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
  • Vercel Deployment:
vercel env add DATABASE_URL
vercel env add SECRET_KEY
vercel env add DEBUG
vercel --prod
  • Data Encryption:
core/settings.py
# core/settings.py
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
  • Rate Limiting:
accounts/views.py
# accounts/views.py
from django_ratelimit.decorators import ratelimit

@ratelimit(key='ip', rate='5/m')
def login_view(request):
    ...
  • Security Headers:
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'csp.middleware.CSPMiddleware',
]

CSP_DEFAULT_SRC = ("'self'", "cdn.vercel.app")
accounts/tests/test_auth.py
1# accounts/tests/test_auth.py
2class AuthenticationTests(TestCase):
3    def test_user_registration(self):
4        response = self.client.post(reverse('signup'), {
5            'email': 'test@example.com',
6            'password1': 'complexpassword123',
7            'password2': 'complexpassword123',
8            'phone_number': '+254712345678',
9            'date_of_birth': '2000-01-01'
10        })
11        self.assertEqual(response.status_code, 302)
12        self.assertEqual(User.objects.count(), 1)

Common Issues:

  • Database Connection Errors:
# Test Supabase connection
psql "$DATABASE_URL"

# Check SSL configuration
openssl s_client -connect db.project-ref.supabase.co:6543
  • Static Files Not Loading:
# Collect static files
python manage.py collectstatic --noinput

# Verify vercel.json routes
  • Authentication Failures:
# Check email verification status
user = CustomUser.objects.get(email='user@example.com')
print(user.is_verified)

Check out the demo

Check out the source code

Share on LinkedIn
Share on X
Share on Facebook
Share on WhatsApp
Share on Telegram
Share via Email
Copy Link

Ready to take your business to the next level? Let’s make it happen.