Skip to content

Commit

Permalink
New Structure
Browse files Browse the repository at this point in the history
  • Loading branch information
mariofix committed Sep 21, 2024
1 parent e46d7e5 commit 983f52a
Show file tree
Hide file tree
Showing 17 changed files with 273 additions and 260 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

.vscode
merchants_orig
store
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Merchants is released under the MIT License. See the [LICENSE](LICENSE) file for

## Acknowledgements

This project was inspired by the django-payments library and aims to provide similar functionality for FastAPI
This project was inspired by the [django-payments](https://github.com/jazzband/django-payments) library and aims to provide similar functionality for FastAPI
applications, some parts were made with Claude and/or ChatGPT.

## Changelog
Expand Down
6 changes: 3 additions & 3 deletions alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
if config.config_file_name is not None:
fileConfig(config.config_file_name)

from merchants.config import settings # noqa
from store.config import settings # noqa

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

target_metadata = DatabaseModel.metadata

Expand All @@ -28,7 +28,7 @@


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


def run_migrations_offline():
Expand Down
86 changes: 0 additions & 86 deletions alembic/versions/6d833540bc9e_re_8_init.py

This file was deleted.

38 changes: 0 additions & 38 deletions merchants/FastapiAdmin.py

This file was deleted.

21 changes: 0 additions & 21 deletions merchants/FastapiApp.py

This file was deleted.

30 changes: 30 additions & 0 deletions merchants/StarletteAdmin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# from starlette_admin.contrib.sqla import Admin

# from merchants.database import engine

# admin = Admin(engine, title="Merchants Admin")


class IntegrationAdminMixin:
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 PaymentAdminMixin:
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(PaymentAdmin(Payment, icon="fas fa-wallet"))
# admin.add_view(IntegrationAdmin(Integration, icon="fas fa-list"))
47 changes: 47 additions & 0 deletions merchants/StarletteApp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from typing import Any

import rich
from fastapi import APIRouter, Body, Request

# from merchants.config import settings
# from merchants.FastapiAdmin import admin
# from merchants.version import __version__ as __merchants_version__

fastapi_route = APIRouter()

# app = FastAPI(
# title=settings.PROJECT_NAME,
# version=__merchants_version__,
# description="A unified payment processing toolkit for Starlette/FastAPI applications",
# debug=settings.DEBUG,
# )

default_body = Body(None)


@fastapi_route.post(
"/update-payment/{integration}",
name="update_payment",
description="This route processes the status updates from the integrations.",
)
async def update_payment(
integration: str,
request: Request,
body_payload: Any = default_body,
):
rich.print(f"{body_payload = }")
rich.print(f"{integration = }")
rich.print(f"{request.headers = }")
rich.print(f"{request.query_params = }")
body = await request.body()
rich.print(f"{body = }")
return {"message": "Hello World"}


# app.include_router(app_route, prefix=settings.MERCHANTS_API_ROUTER_PREFIX)
# admin.debug = app.debug
# admin.mount_to(app)


# url_list = [{"path": route.path, "name": route.name} for route in app.routes]
# rich.print(url_list)
12 changes: 12 additions & 0 deletions merchants/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import Any

# Intentionally the same structure as django-payments for compatibility reasons
INTEGRATIONS: dict[str, tuple[str, dict]] = {
"default": (
"merchants.integrations.dummy",
{},
),
}


INTEGRATIONS_CACHE: dict[str, Any] = {}
46 changes: 46 additions & 0 deletions merchants/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import rich


def integration_factory(slug: str, config: dict):
rich.print(f"Creating integration {slug} ...")

return {}


def find_integration(slug: str):
rich.print(f"Searching for integration: {slug} ...")

return {
"name": "Simple Integration",
"slug": "dummy",
"is_active": True,
"integration_class": "merchants.integrations.dummy",
"config": {
"not_needed": True,
},
}


def load_integration(slug: str):
rich.print(f"Loading {slug} to cache...")


def process_payment(payment):
rich.print(payment)

if payment.status not in ["created"]:
raise AttributeError("Only created payments can start the process.")

integration, _ = find_integration(payment.integration_slug)
# if not payment.integration_id:
# if getattr(settings, "LOAD_FROM_DATABASE", None):
# integration_config = None
# else:
# integration_config = getattr(settings, payment.integration_slug, None)
# else:
# rich.print(f"Using integration: {payment.integration} ...")
# integration_config = payment.integration.config

rich.print(f"{integration = }")

return payment
30 changes: 7 additions & 23 deletions merchants/config.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
import secrets

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


class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_ignore_empty=True, extra="ignore")
SECRET_KEY: str = secrets.token_urlsafe(32)
USE_HTTPS: bool = False
DOMAIN: str = "tardis.local"
DEBUG: bool = True

@computed_field # type: ignore[prop-decorator]
@property
def server_host(self) -> str:
if self.USE_HTTPS:
return f"https://{self.DOMAIN}"
return f"http://{self.DOMAIN}"

PROJECT_NAME: str = "Merchants"
SENTRY_DSN: HttpUrl | None = None

SQLALCHEMY_DATABASE_URL: str = "sqlite:///merchants.db"
PROCESS_ON_SAVE: bool = True
"""Process the payment before commiting to database."""

ALLOWED_DOMAINS: list[str] | None = None
LOAD_FROM_DATABASE: bool = False
"""Retrieves Integrations from database."""

PROCESS_ON_SAVE: bool = True
API_ROUTER_PREFIX: str = "/merchants"
"""Base URI for Application."""


settings = Settings() # type: ignore
2 changes: 2 additions & 0 deletions merchants/crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def get_integration(slug: str) -> dict:
return {}
18 changes: 0 additions & 18 deletions merchants/database.py

This file was deleted.

Loading

0 comments on commit 983f52a

Please sign in to comment.