Skip to content

Commit

Permalink
payment model, sqlmodel drop
Browse files Browse the repository at this point in the history
  • Loading branch information
mariofix committed Sep 19, 2024
1 parent 1d697f4 commit 659f75a
Show file tree
Hide file tree
Showing 14 changed files with 241 additions and 174 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12"]
poetry-version: ["1.8.3"]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Merchants
# Fastapi-Merchants

[![PyPI version](https://badge.fury.io/py/merchants.svg)](https://badge.fury.io/py/merchants)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python Versions](https://img.shields.io/pypi/pyversions/merchants.svg)](https://pypi.org/project/merchants/)
[![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=for-the-badge&logo=fastapi)](https://fastapi.tiangolo.com)
[![Downloads](https://pepy.tech/badge/merchants)](https://pepy.tech/project/merchants)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![pre-commit.ci sandbox](https://results.pre-commit.ci/badge/github/mariofix/merchants/sandbox.svg)](https://results.pre-commit.ci/latest/github/mariofix/merchants/sandbox)

A unified payment processing toolkit for FastAPI applications, inspired by django-payments.

Expand All @@ -17,7 +18,7 @@ flexible interface for handling different payment methods.

## Features

- Easy integration with FastAPI applications
- Easy integration with Starlette/FastAPI applications
- Support for multiple payment gateways
- Customizable payment workflows
- Webhook handling for payment status updates
Expand Down
2 changes: 1 addition & 1 deletion alembic/README
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Generic single-database configuration.
Generic single-database configuration.
13 changes: 6 additions & 7 deletions alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool
from sqlalchemy import engine_from_config, pool

from alembic import context
import os

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
Expand All @@ -15,12 +13,13 @@
if config.config_file_name is not None:
fileConfig(config.config_file_name)

from merchants.config import settings # noqa

# add your model's MetaData object here
# for 'autogenerate' support
from merchants.models import SQLModel # noqa
from merchants.config import settings # noqa
from merchants.models import DatabaseModel # noqa

target_metadata = SQLModel.metadata
target_metadata = DatabaseModel.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
Expand All @@ -29,7 +28,7 @@


def get_url():
return str(settings.SQLALCHEMY_DATABASE_URI)
return str(settings.SQLALCHEMY_DATABASE_URL)


def run_migrations_offline():
Expand Down
1 change: 0 additions & 1 deletion alembic/script.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Create Date: ${create_date}
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
${imports if imports else ""}

# revision identifiers, used by Alembic.
Expand Down
58 changes: 0 additions & 58 deletions alembic/versions/270409ec074b_re_2_init.py

This file was deleted.

82 changes: 82 additions & 0 deletions alembic/versions/96ae93cc9125_re_7_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""(re-7)Init
Revision ID: 96ae93cc9125
Revises:
Create Date: 2024-09-19 04:51:55.007209
"""

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "96ae93cc9125"
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"integration",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.Column("slug", sa.String(length=255), nullable=False),
sa.Column("integration_class", sa.String(length=255), nullable=True),
sa.Column("config", sa.JSON(), nullable=True),
sa.Column(
"created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False
),
sa.Column(
"modified_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("slug"),
)
op.create_table(
"user",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("username", sa.String(length=3), nullable=False),
sa.Column("email", sa.String(length=255), nullable=False),
sa.Column("password", sa.String(length=255), nullable=False),
sa.Column("scopes", sa.JSON(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("email"),
sa.UniqueConstraint("username"),
)
op.create_table(
"payment",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("transaction", sa.String(length=255), nullable=False),
sa.Column("amount", sa.Numeric(precision=10, scale=2), nullable=False),
sa.Column("currency", sa.String(length=3), nullable=False),
sa.Column("customer_email", sa.String(length=255), nullable=False),
sa.Column("integration_slug", sa.String(length=255), nullable=False),
sa.Column("integration_id", sa.Integer(), nullable=True),
sa.Column("status", sa.String(length=10), nullable=False),
sa.Column("integration_payload", sa.JSON(), nullable=True),
sa.Column("integration_response", sa.JSON(), nullable=True),
sa.Column(
"created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False
),
sa.Column(
"modified_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False
),
sa.ForeignKeyConstraint(
["integration_id"],
["integration.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("transaction"),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("payment")
op.drop_table("user")
op.drop_table("integration")
# ### end Alembic commands ###
19 changes: 13 additions & 6 deletions merchants/FastapiAdmin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from merchants.models import User, Broker
from merchants.database import engine
from merchants.config import settings
from starlette_admin.contrib.sqla import Admin, ModelView

from starlette_admin.contrib.sqlmodel import Admin, ModelView
from merchants.config import settings
from merchants.database import engine
from merchants.models import Integration, Payment, User

admin = Admin(engine, title=settings.PROJECT_NAME)

Expand All @@ -13,13 +13,20 @@ class UserAdmin(ModelView):
exclude_fields_from_edit = ["id"]


class BrokerAdmin(ModelView):
class IntegrationAdmin(ModelView):
exclude_fields_from_list = ["id", "config"]
exclude_fields_from_create = ["id"]
exclude_fields_from_edit = ["id"]
fields_default_sort = ["slug"]
searchable_fields = ["name", "slug", "integration_class", "config"]


class PaymentAdmin(ModelView):
exclude_fields_from_list = ["id", "integration_slug", "integration_payload", "integration_response", "modified_at"]
exclude_fields_from_create = ["id"]
exclude_fields_from_edit = ["id"]


admin.add_view(UserAdmin(User, icon="fas fa-person"))
admin.add_view(BrokerAdmin(Broker, icon="fas fa-list"))
admin.add_view(PaymentAdmin(Payment, icon="fas fa-wallet"))
admin.add_view(IntegrationAdmin(Integration, icon="fas fa-list"))
39 changes: 4 additions & 35 deletions merchants/FastapiApp.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,17 @@
from fastapi import FastAPI, Depends, Request
from fastapi.routing import APIRoute
from sqlmodel import Session
from collections.abc import Generator
from typing import Annotated
from merchants.version import __version__ as __merchants_version__
from debug_toolbar.middleware import DebugToolbarMiddleware
from fastapi import FastAPI

from merchants.config import settings
from merchants.database import engine

from merchants.FastapiAdmin import admin


from debug_toolbar.middleware import DebugToolbarMiddleware
from debug_toolbar.panels.sqlalchemy import SQLAlchemyPanel


def custom_generate_unique_id(route: APIRoute) -> str:
return f"{route.tags[0]}-{route.name}"


def get_db() -> Generator[Session, None, None]:
with Session(engine) as session:
yield session


SessionDep = Annotated[Session, Depends(get_db)]


class SQLModelPanel(SQLAlchemyPanel):
async def add_engines(self, request: Request):
self.engines.add(engine)

from merchants.version import __version__ as __merchants_version__

app = FastAPI(
title=settings.PROJECT_NAME,
# generate_unique_id_function=custom_generate_unique_id,
version=__merchants_version__,
description="Universal Payment Processing System",
debug=True,
)
app.add_middleware(
DebugToolbarMiddleware,
panels=["merchants.FastapiApp.SQLModelPanel"],
)
app.add_middleware(DebugToolbarMiddleware)

admin.mount_to(app)

Expand Down
8 changes: 5 additions & 3 deletions merchants/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import secrets
from typing import List

from pydantic import HttpUrl, computed_field
from pydantic_settings import BaseSettings, SettingsConfigDict

Expand All @@ -21,9 +21,11 @@ def server_host(self) -> str:
PROJECT_NAME: str = "Merchants"
SENTRY_DSN: HttpUrl | None = None

SQLALCHEMY_DATABASE_URI: str = "sqlite:///merchants.db"
SQLALCHEMY_DATABASE_URL: str = "sqlite:///merchants.db"

ALLOWED_DOMAINS: list[str] | None = None

ALLOWED_DOMAINS: List[str] | None = None
PROCESS_ON_SAVE: bool = True


settings = Settings() # type: ignore
15 changes: 12 additions & 3 deletions merchants/database.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
from sqlmodel import Session, create_engine, select
from merchants.config import settings
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

from merchants.config import settings

engine = create_engine(
settings.SQLALCHEMY_DATABASE_URI,
settings.SQLALCHEMY_DATABASE_URL,
pool_recycle=1800,
pool_pre_ping=True,
connect_args={"check_same_thread": False},
)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine,
)
DatabaseModel = declarative_base()
Loading

0 comments on commit 659f75a

Please sign in to comment.