{"id":28331038,"url":"https://github.com/mojtaba-arvin/django-react-iou-bnpl","last_synced_at":"2026-01-25T09:36:04.210Z","repository":{"id":295204435,"uuid":"989410278","full_name":"mojtaba-arvin/django-react-iou-bnpl","owner":"mojtaba-arvin","description":"A full-stack BNPL system using an I.O.U-based installment model, built with Django and React.js. It features a Private/Assigned Plan model where merchants assign plans to customers, and is designed to support Public Plans in the future for broader accessibility.","archived":false,"fork":false,"pushed_at":"2025-06-14T06:16:22.000Z","size":175,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-14T07:30:01.624Z","etag":null,"topics":["bnpl","buy-now-pay-later","celery","django","docker","drf","github-actions","installment-plan","jwt","postgresql","pytest","python","redis","rest-api","structlog","swagger"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mojtaba-arvin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-24T03:36:54.000Z","updated_at":"2025-06-14T06:16:25.000Z","dependencies_parsed_at":"2025-05-24T07:37:12.324Z","dependency_job_id":"4b409fc5-f15b-4c73-b0c1-b5a6d170ec07","html_url":"https://github.com/mojtaba-arvin/django-react-iou-bnpl","commit_stats":null,"previous_names":["mojtaba-arvin/django-react-iou-bnpl"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mojtaba-arvin/django-react-iou-bnpl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mojtaba-arvin%2Fdjango-react-iou-bnpl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mojtaba-arvin%2Fdjango-react-iou-bnpl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mojtaba-arvin%2Fdjango-react-iou-bnpl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mojtaba-arvin%2Fdjango-react-iou-bnpl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mojtaba-arvin","download_url":"https://codeload.github.com/mojtaba-arvin/django-react-iou-bnpl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mojtaba-arvin%2Fdjango-react-iou-bnpl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28750875,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T09:00:19.176Z","status":"ssl_error","status_checked_at":"2026-01-25T09:00:04.131Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bnpl","buy-now-pay-later","celery","django","docker","drf","github-actions","installment-plan","jwt","postgresql","pytest","python","redis","rest-api","structlog","swagger"],"created_at":"2025-05-26T18:09:01.285Z","updated_at":"2026-01-25T09:36:04.204Z","avatar_url":"https://github.com/mojtaba-arvin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BNPL Project\n\n![Python Version](https://img.shields.io/badge/python-3.13-blue)\n![Django Version](https://img.shields.io/badge/django-5.2.1-green)\n![React Version](https://img.shields.io/badge/react-19.1.0-blue)\n![Microfrontend](https://img.shields.io/badge/architecture-microfrontend-orange)\n![License](https://img.shields.io/github/license/mojtaba-arvin/django-react-iou-bnpl)\n![Build](https://github.com/mojtaba-arvin/django-react-iou-bnpl/actions/workflows/backend-tests.yml/badge.svg)\n\nA full-stack **Buy Now, Pay Later (BNPL)** system based on an **I.O.U-based installment loan model**, built with **Django** and **React.js** with **TypeScript**, using **Micro-Frontend** architecture.\n\nIt follows a **Private/Assigned Plan** structure, where merchants assign installment plans to specific customers. The system includes separate **react-admin** panels under ‍‍`customer/*` and `merchant/*`, with login access restricted to the user's account type.\n\n## Table of Contents\n\n- [Frontend Features](#frontend-features)\n  - [Architecture](#architecture)\n  - [Auth \u0026 Data](#auth--data)\n  - [Testing \u0026 Quality](#testing--quality)\n  - [Observability](#observability)\n- [Backend Features](#backend-features)\n  - [Architecture \u0026 Code Design](#architecture--code-design)\n  - [Authentication \u0026 Permissions](#authentication--permissions)\n  - [Tooling](#tooling)\n  - [API Documentation](#api-documentation)\n  - [CI/CD \u0026 Test Automation](#cicd--test-automation)\n  - [Installments \u0026 Plans Logic](#installments--plans-logic)\n  - [Background Tasks (Celery)](#background-tasks-celery)\n  - [User Management](#user-management)\n  - [DB Models](#db-models)\n- [Getting Started](#getting-started-development)\n  - [Prerequisites](#prerequisites)\n  - [Development Setup](#step-1-copy-env-file-to-configre)\n- [Project Structures](#project-structures)\n- [Tech Stacks](#tech-stacks)\n- **[Demo Walkthrough](#demo-walkthrough)**\n\n## \u003ca id=\"frontend-features\"\u003e\u003c/a\u003eFrontend Features\n\n### \u003ca id=\"architecture\"\u003e\u003c/a\u003eArchitecture\n\n- **Micro‑Frontend (Module Federation)** – Runtime loading of independent React apps, enabling parallel development and isolated deployments.\n- **Clean Architecture** – Separation into Presentation, Application, Infrastructure and Domain layers to enhance modularity and testability.\n\n### \u003ca id=\"auth--data\"\u003e\u003c/a\u003eAuth \u0026 Data\n\n- **Auth Provider** – JWT authentication flow with automatic access and refresh token handling for secure session management.\n- **Data Provider** – React-Admin compatible API client with error handler decorator.\n\n### \u003ca id=\"testing--quality\"\u003e\u003c/a\u003eTesting \u0026 Quality\n\n- **Jest** – Comprehensive tests for components and utilities to ensure code reliability.\n- **Prettier \u0026 ESLint** - Automated code formatting and linting to enforce style consistency and catch errors early.\n\n### \u003ca id=\"observability\"\u003e\u003c/a\u003eObservability\n\n- **OpenTelemetry Integration** – Capturing frontend metrics and traces for end-to-end performance monitoring and sensitive fields in request metadata are automatically redacted to protect personal data.\n\n## \u003ca id=\"backend-features\"\u003e\u003c/a\u003eBackend Features\n\n### \u003ca id=\"architecture--code-design\"\u003e\u003c/a\u003eArchitecture \u0026 Code Design\n\n- **Separated view and service logic** – Follows clean architecture principles, aiding in maintainability and testing.\n- **DRF-compatible Standardized API response mixin** – Provides uniform success/error response formats, improving client integration and Swagger docs clarity.\n- **Custom DRF exception handler** – Standardizes error responses, making debugging and frontend handling more consistent\n- **Base business exception class** – Centralizes business logic exceptions, enabling more structured error handling.\n- **Unified paginated list responses** – Ensures consistent pagination output, reducing frontend complexity.\n- **Modular Django settings (development/production)** – Simplifies environment-based configuration management with proper type casting.\n\n### \u003ca id=\"authentication--permissions\"\u003e\u003c/a\u003eAuthentication \u0026 Permissions\n\n- **Reject tokens if user is inactive** – Enhances security by invalidating access even with a valid token.\n- **Custom JWT for skipping expired tokens on public endpoints** – Allows anonymous access without breaking flow, improving public endpoint UX.\n- **Custom DRF permission classes** – Improves UX by showing specific access error messages.\n- **Object-level permission view mixin** – Provides auto-checks in viewsets with reusable logic\n\n### \u003ca id=\"tooling\"\u003e\u003c/a\u003eTooling\n\n- **Structured logging with JSON format (structlog)** – Supports modern observability tools like ELK or Datadog.\n- **FactoryBoy + DRF APITestCase** – Allows fast, isolated, and reusable tests, boosting test coverage and quality.\n- **PEP8, typing, and Google docstrings** – Increases code readability, maintainability, and quality.\n\n### \u003ca id=\"api-documentation\"\u003e\u003c/a\u003eAPI Documentation\n\n- **Swagger schema utilities for response documentation** – Improves API clarity and keeps documentation aligned with real behavior.\n\n### \u003ca id=\"cicd--test-automation\"\u003e\u003c/a\u003eCI/CD \u0026 Test Automation\n\n- **Prebuilt Docker image for backend CI** – Reduces CI time by skipping local build and using cached layers.\n- **GitHub workflow: backend tests with concurrency rules** – Smart test runs based on event type, skipping unnecessary builds.\n- **Test artifacts: logs and coverage reports** – Enhances CI transparency and developer feedback loops.\n\n### \u003ca id=\"installments--plans-logic\"\u003e\u003c/a\u003eInstallments \u0026 Plans Logic\n\n- **Bulk create installments via thread-local flag for signal** – Optimizes mass insert operations and automates setup logic.\n- **Signal for updating installment plan status** – Keeps data integrity by reflecting changes in related models.\n- **Installment conflict prevention checks** – Prevents logic bugs like double payments or out-of-sequence transactions.\n- **Conditional UniqueConstraint and CheckConstraint** – Enforces business rules at the DB level, protecting data consistency for unique installment sequence and due date per plan with correct amount\n\n### \u003ca id=\"background-tasks-celery\"\u003e\u003c/a\u003eBackground Tasks (Celery)\n\n- **Celery tasks for reminders and overdue checks** – Adds scalability by offloading background operations.\n- **Separated Celery workers as Docker services** - helps decouple task processing from the main API which improves maintainability, scalability, and fault tolerance of the system.\n\n### \u003ca id=\"user-management\"\u003e\u003c/a\u003eUser Management\n\n- **Signals for customer/merchant profile creation** – Automates related object creation, ensuring consistency.\n- **Auto approve merchants and customer credits in debug mode** – Speeds up development/testing by bypassing manual checks.\n- **DRF-based unique email validation + Django password validation** – Ensures secure user creation.\n- **Custom UserManager + Support the Group and Permission models** – Enables extensible user creation logic and permission handling.\n\n### \u003ca id=\"db-models\"\u003e\u003c/a\u003eDB Models\n\n- **Abstract base model to add timestamps with indexed created_at** – Improves database efficiency for ordering/filtering operations.\n- **Future-proof database design with abstracted plan-customer relation** – The system avoids directly linking `Plan -\u003e Customer` to enable future support for Public Plans. Instead, it introduces an intermediate `InstallmentPlan` that connects a `Plan` (owned by a merchant)\nto a `User` (the customer), providing flexibility for both assigned and publicly available plans.\n\n## \u003ca id=\"getting-started-development\"\u003e\u003c/a\u003eGetting started (Development)\n\n### \u003ca id=\"prerequisites\"\u003e\u003c/a\u003ePrerequisites\n\nMake sure you have the following installed on your system:\n\n- [Docker](https://docs.docker.com/get-docker/)\n- [Docker Compose](https://docs.docker.com/compose/install/)\n\n### \u003ca id=\"step-1-copy-env-file-to-configre\"\u003e\u003c/a\u003eStep 1: Copy `.env` file to configre\n\nCreate a .env file by copying the example configuration:\n\n```bash\ncp .env.example .env\n```\n\n#### ⚠️ To development set correct file permissions with UID/GID (Optional but recommended)\n\nThe containers run using the same **user ID (UID)** and **group ID (GID)** as your host machine, defined via `HOST_UID` and `HOST_GID` in the `.env` file.\nThis prevents permission issues when writing files (e.g., migrations, logs) from within containers to your local file system.\n\n**Note:** If you're using **Linux** and your UID and GID are both **1000**, which is common for the first local user, you can skip this step — the default values will work just fine.\n\nIf you're unsure, you can find your host UID and GID by running:\n\n```bash\nid -u \u0026\u0026 id -g\n```\n\n### Step 2: Start backend required services\n\nUse the following command to start **PostgreSQL**, **Redis**, and the **API service**:\n\n```bash\ndocker compose -f docker-compose.dev.yml up -d bnpl-db bnpl-redis bnpl-api\n```\n\n#### ⚠️ Healthchecks Note\n\nServices will only start once their dependencies are marked as healthy.\n\n- **PostgreSQL** has a `pg_isready` check.\n- **Redis** uses `redis-cli ping`.\n\nThis may _take a few seconds_ depending on your system.\n\n### Step 3: Enter the API container\n\n```bash\ndocker compose -f docker-compose.dev.yml exec bnpl-api /bin/sh\n```\n\n### Step 4: Apply migrations and run the Django development server\n\nOnce inside the container, run the following commands to initialize the database:\n\n```bash\npython manage.py migrate\n```\n\nThis applies any outstanding database migrations.\n\nIf you may also want to use the Django `admin` dashboard feature, you need to create a superuser:\n\n```bash\npython manage.py createsuperuser\n```\n\nAfterward, start the Django development server. It binds to `0.0.0.0`, making it accessible from outside the container:\n\n```bash\npython manage.py runserver 0.0.0.0:8000\n```\n\n**Note:** You only need to run `migrate` the first time or whenever new migrations are added to the project.\n\n### Step 5 (Optional): Start Celery background workers as separate Docker services\n\nThe project uses **Celery** to handle asynchronous tasks such as background processing and scheduled jobs.\nRunning Celery as separate services helps **decouple task processing from the main API**, which improves maintainability, scalability, and fault tolerance of the system.\n\nStart both the **worker** and **beat** services using the following command:\n\n```bash\ndocker compose -f docker-compose.dev.yml up -d bnpl-worker bnpl-beat\n```\n\n### Step 6: Start frontend service\n\nTo start the **Node** development environment for **React.js**, use the following command:\n\n```bash\ndocker compose -f docker-compose.dev.yml up -d bnpl-frontend\n```\n\n### Step 7: Enter the frontend container\n\nRun the following command to enter the **frontend** container:\n\n```bash\ndocker compose -f docker-compose.dev.yml exec bnpl-frontend /bin/sh\n```\n\n### Step 8: Install packages and run the development script\n\nOnce inside the container, execute the following commands to install the necessary packages and run the development script. (The script will launch with the parallel flag to start remote services and the shell application.)\n\n```bash\npnpm install\npnpm dev\n```\n\n- **Shell homepage:** [http://localhost:3000](http://localhost:3000)\n- **Customer admin panel:** Accessible under `customer/*`\n- **Merchant admin panel:** Accessible under `merchant/*`\n\n**Note:** Users can only log in according to their account type. Login to other account types is restricted.\n\n**Note:** All frontend default settings are located at ‍‍‍\n\n```bash\nfrontend/shared/src/infrastructure/context/global-settings.context.tsx‍\n```\n\nFor new **environment** variables, they must be defined with the webpack **DefinePlugin** for both shell and remote apps.\n\n#### Optional: Standalone Development (for development purposes)\n\n- **customer standalone:**\n\n```bash\npnpm dev:standalone --filter @bnpl/merchant-app\n```\n\nCustomer standalone will be available at: [http://localhost:3001](http://localhost:3001)\n\n**merchant standalone:**\n\n```bash\npnpm dev:standalone --filter @bnpl/customer-app\n```\n\nMerchant standalone will be available at: [http://localhost:3002](http://localhost:3002)\n\n### Explore Backend API endpoints via Swagger UI (development environment only)\n\n### Swagger UI\n\nOnce the development server is running, you can browse and try all available API endpoints using Swagger UI:\n\nOpen: [http://localhost:8000/swagger/](http://localhost:8000/swagger/)\n\n### API endpoints\n\n#### Authentication\n\n`POST /api/auth/register/` — Register a new user (as Customer or Merchant)\n\n`POST /api/auth/token/` — Obtain access and refresh JWT tokens\n\n`POST /api/auth/token/refresh/` — Refresh your access token using a refresh token\n\n---\n\n#### Customers\n\n`GET /api/customers/eligible/` — List eligible customers (merchant-only access) by email search, useful when assigning customer IDs during private plan creation\n\n**Eligible customers definition:**\n\n- The customer's profile must be **active**, meaning they are allowed to use BNPL services\n- The customer's credit score status must be set to **approved**\n\n---\n\n#### Installments and Plans\n\n`GET /api/installments/` — list installments with filtering upcoming/past (owner customer-only access)\n\n`POST /api/installments/{id}/pay/` — Pay for a specific installment (owner customer-only access)\n\n`POST /api/plans/` — Create a new installment plan (verified merchant-only access)\n\n **Features:**\n\n- Installments are created in `bulk`, improving performance and scalability.\n- A thread-local flag is used to skip signal-based creation, preventing redundant processing during batch operations.\n\n`GET /api/plans/` — List all existing installment plans for both customers and merchants access\n\n**Customer view:**\n\n- Lists only installment plans associated to the customer.\n\n**Merchant view:**\n\n- Lists only installment plans created by the current merchant.\n- includes customer_email field\n\n`GET /api/plans/{id}/` — retrieve the details of a specific installment plan with object-level access for customers and merchants\n\n---\n\n#### Analytics\n\n`GET /api/analytics/dashboard/` — Overview of key business metrics (merchant-only access)\n\n- includes total revenue, success rate, total overdue and total active_plans\n\n---\n\n### Django Admin panel (useful during development)\n\nIf you created a superuser, you can access the Django admin interface at:\n\n[http://localhost:8000/admin/](http://localhost:8000/admin/)\n\n- User model includes **inline editing** for CustomerProfile and MerchantProfile.\n- Show **clickable links** to the related Plan and Customer (User), for fast navigation and context.\n\n## \u003ca id=\"project-structures\"\u003e\u003c/a\u003eProject Structure (Backend)\n\n```bash\n.\n├── bnpl/                  # Django project (settings, wsgi, celery)\n├── core/                  # Shared utilities, exceptions, base logic\n├── account/               # Authentication, user management\n├── customer/              # Customer-related models and logic\n├── merchant/              # Merchant models and logic\n├── plan/                  # Installment plan logic\n├── installment/           # Payment installments\n├── analytics/             # Reporting and dashboards\n├── notification/          # Notification system\n├── requirements.txt\n├── requirements-dev.txt\n├── manage.py\n└── Dockerfile.dev\n```\n\n## Project Structure (Frontend)\n\n```bash\n.\n├── shell/                    # Host app\n├── customer-app/             # Remote Customer app\n├── merchant-app/             # Remote Merchant app\n├── shared/                   # Shared modules and utilities\n├── package.json\n├── pnpm-workspace.yaml\n└── Dockerfile.dev\n```\n\n## \u003ca id=\"tech-stacks\"\u003e\u003c/a\u003eBackend Tech Stack\n\n| Layer           | Technology                           | Notes                                |\n| --------------- | ------------------------------------ | ------------------------------------ |\n| **Backend**     | Django 5.2, DRF 3.16, SimpleJWT      | RESTful APIs, Auth (JWT)             |\n| **Async Tasks** | Celery 5.5 + Redis                   | Background jobs (e.g. notifications) |\n| **Database**    | PostgreSQL 15+ (via psycopg2-binary) | Relational DB                        |\n| **Config**      | python-decouple                      | `.env`-based settings                |\n| **Logging**     | structlog                            | Structured \u0026 readable logging        |\n| **API Docs**    | drf-yasg                             | Swagger UI, OpenAPI schema           |\n| **CORS**        | django-cors-headers                  | Cross-Origin requests for APIs       |\n| **Testing**     | pytest, pytest-django, factory_boy   | Automated unit \u0026 integration tests   |\n| **DevOps**      | Docker, GitHub Actions               | Containerized app, CI/CD ready       |\n| **Scheduling**  | django-celery-beat                   | Periodic task support                |\n\n## Frontend Tech Stack\n\n| Layer              | Technology                           | Notes                              |\n| ------------------ | ------------------------------------ | ---------------------------------- |\n| **Frontend**       | React 19.1, TypeScript, react-admin  | Admin interfaces                   |\n| **Micro-Frontend** | Webpack 5, Module Federation         | Runtime dynamic module loading     |\n| **State \u0026 Data**   | @tanstack/react-query, axios         | Server state fetching, HTTP client |\n| **Routing**        | react-router-dom                     | Client-side routing                |\n| **Auth**           | jwt-decode                           | Decode JWTs on client              |\n| **Observability**  | OpenTelemetry Web SDK, OTLP exporter | Frontend tracing \u0026 metrics         |\n| **Testing**        | Jest, @testing-library/react         | Component \u0026 integration tests      |\n| **Monorepo**       | pnpm workspaces                      | Multi-package management           |\n\n## \u003ca id=\"demo-walkthrough\"\u003e\u003c/a\u003eDemo Walkthrough\n\n### 1. Home Page\n\n![Shell Home Page](docs/assets/01-shell-home-page.png)\n**Shell Homepage:** [http://localhost:3000](http://localhost:3000)\n\n---\n\n### 2. Customer Registration Page\n\nFirst, register as a customer by creating an account with the email `customer1@example.com`. This account will be used later to assign a plan.\n\n![Customer Register Page](docs/assets/02-customer-register-page.png)\n**Customer Registration Page:** [http://localhost:3000/customer/register](http://localhost:3000/customer/register)\n\n---\n\n### 3. Merchant Registration Page\n\nNext, register as a merchant by creating an account with the email `merchant1@example.com`.\n\n![Merchant Register Page](docs/assets/03-merchant-register-page.png)\n**Merchant Registration Page:** [http://localhost:3000/merchant/register](http://localhost:3000/merchant/register)\n\n---\n\n### 4. Merchant Login Page\n\nLogin as a merchant using the account you just created (`merchant1@example.com`).\n\n![Merchant Login Page](docs/assets/04-merchant-login-page.png)\n**Merchant Login Page:** [http://localhost:3000/merchant/login](http://localhost:3000/merchant/login)\n\n---\n\n### 5. Merchant Plans Page\n\nAs a merchant, navigate to the plans list. Initially, this list will be empty.\n\n![Merchant Plans Page](docs/assets/05-merchant-plans-page.png)\n**Merchant Plans Page:** [http://localhost:3000/merchant/plans](http://localhost:3000/merchant/plans)\n\n---\n\n### 6. Create a Plan\n\nTo create a new plan, enter the amount. As you type in the `Installment Count`, the preview of installments will appear. Then, start typing the first characters of the customer's email to search and select it.\n\n![Merchant Create Plan Page](docs/assets/06-merchant-create-plan-page.png)\n**Create a Plan:** [http://localhost:3000/merchant/plans/create](http://localhost:3000/merchant/plans/create)\n\n---\n\n### 7. Plan Details\n\nAfter successfully creating the plan, you will be redirected to the plan details page.\n\n![Merchant Plan Details Page](docs/assets/07-merchant-plan-details.png)\n\n---\n\n### 8. Login as Customer to View Installments\n\nLogin with the customer account `customer1@example.com` to view the installments, also you can filter them with upcoming/past status.\n\n![Customer Installments Page](docs/assets/08-customer-installments-page.png)\n**Customer Installments Page:** [http://localhost:3000/customer/installments](http://localhost:3000/customer/installments)\n\n---\n\n### 9. Click on 'Pay Now'\n\nOn the customer installments page, click the `Pay Now` button to initiate payment.\n\n![Pay Now Button](docs/assets/09-customer-pay-now.png)\n\n---\n\n### 10. Merchant Dashboard Update\n\nLogin as a merchant to see the updated metrics in the merchant dashboard after the customer has made a payment.\n\n![Merchant Dashboard](docs/assets/10-merchant-dashboard.png)\n**Merchant Dashboard:** [http://localhost:3000/merchant/](http://localhost:3000/merchant/)\n\n---\n\n### 11. Merchant Plans List with Progress\n\nFinally, view the updated merchant plans list, which now shows the progress for each plan.\n\n![Merchant Plans Page with Progress](docs/assets/11-merchant-plans-page.png)\n**Merchant Plans Page:** [http://localhost:3000/merchant/plans](http://localhost:3000/merchant/plans)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmojtaba-arvin%2Fdjango-react-iou-bnpl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmojtaba-arvin%2Fdjango-react-iou-bnpl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmojtaba-arvin%2Fdjango-react-iou-bnpl/lists"}