Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ COPY pyproject.toml pyproject.toml

RUN pip install poetry
RUN poetry config virtualenvs.create false
RUN poetry install --no-dev
RUN poetry install --no-root

COPY . /app

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# SQLAlchemy models
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.8'
#version: '3.8'

services:
web:
Expand All @@ -9,7 +9,7 @@ services:
- "8000:8000"
env_file:
- ./ops/environment/.default.env
- ./ops/environment/.local.env
- ops/environment/.env
depends_on:
- db
networks:
Expand Down
3 changes: 2 additions & 1 deletion src/base_settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Optional
import os

from pydantic import (
BaseModel,
Expand Down Expand Up @@ -43,4 +44,4 @@ class ProjectSettings(BaseSettings):
)


base_settings = ProjectSettings()
base_settings = ProjectSettings()
38 changes: 38 additions & 0 deletions src/catalogue/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
ProductDiscount,
ProductImage,
StockRecord,
Basket,
BasketLine,
OrderLine,
Order,
)


Expand Down Expand Up @@ -61,6 +65,36 @@ class ProductDiscountAdmin(ModelView, model=ProductDiscount):
icon = 'fa-solid fa-percent'
category = CATALOGUE_CATEGORY

class BasketAdmin(ModelView, model=Basket):
column_list = [Basket.id, Basket.user_id, Basket.price, Basket.status]
column_searchable_list = [Basket.user_id, Basket.status]
form_columns = ['user_id', 'price', 'status']
icon = 'fa-solid fa-basket-shopping'
category = CATALOGUE_CATEGORY

class BasketLineAdmin(ModelView, model=BasketLine):
column_list = [BasketLine.id, BasketLine.basket_id, BasketLine.product_id, BasketLine.quantity, BasketLine.price]
column_searchable_list = [BasketLine.basket_id, BasketLine.product_id]
form_columns = ['basket_id', 'product_id', 'quantity', 'price']
icon = 'fa-solid fa-cart-shopping'
category = CATALOGUE_CATEGORY

class OrderLineAdmin(ModelView, model=OrderLine):
column_list = [OrderLine.id, OrderLine.product_id, OrderLine.order_id, OrderLine.quantity, OrderLine.price]
column_searchable_list = [OrderLine.product_id, OrderLine.order_id]
form_columns = ['order_id', 'product_id', 'quantity', 'price']
icon = 'fa-solid fa-clipboard-list'
category = CATALOGUE_CATEGORY

class OrderAdmin(ModelView, model=Order):
column_list = [Order.id, Order.number, Order.shipping_method, Order.status, Order.total_price]
column_searchable_list = [Order.shipping_method, Order.status, Order.additional_info]
form_columns = ['number', 'basket_id', 'user_id', 'address_id',
'total_price', 'shipping_price', 'shipping_method',
'status', 'additional_info'
]
icon = 'fa-solid fa-bag-shopping'
category = CATALOGUE_CATEGORY

def register_products_admin_views(admin):
admin.add_view(ProductAdmin)
Expand All @@ -69,3 +103,7 @@ def register_products_admin_views(admin):
admin.add_view(ProductImageAdmin)
admin.add_view(StockRecordAdmin)
admin.add_view(ProductDiscountAdmin)
admin.add_view(BasketAdmin)
admin.add_view(BasketLineAdmin)
admin.add_view(OrderLineAdmin)
admin.add_view(OrderAdmin)
79 changes: 79 additions & 0 deletions src/catalogue/models/database.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from datetime import datetime
from enum import Enum
from decimal import Decimal
from typing import (
List,
Optional,
Expand All @@ -10,6 +12,18 @@
SQLModel,
)

class BasketStatus(str, Enum):
OPEN = "Open"
CLOSED = "Closed"
CANCELLED = "Cancelled"

class OrderStatus(str, Enum):
OPEN = "Open"
PAID = "Paid"
SENT = "Sent"
RECEIVED = "Received"
CANCELLED = "Cancelled"
RETURNED = "Returned"

class Product(SQLModel, table=True):
__tablename__ = 'products'
Expand All @@ -24,6 +38,8 @@ class Product(SQLModel, table=True):
images: List["ProductImage"] = Relationship(back_populates="product")
stock_records: List["StockRecord"] = Relationship(back_populates="product")
discounts: List["ProductDiscount"] = Relationship(back_populates="product")
basket_lines: List["BasketLine"] = Relationship(back_populates="product")
order_lines: List["OrderLine"] = Relationship(back_populates="product")

class ProductCategory(SQLModel, table=True):
__tablename__ = 'product_categories'
Expand Down Expand Up @@ -90,3 +106,66 @@ class ProductDiscount(SQLModel, table=True):
valid_to: datetime

product: Product = Relationship(back_populates="discounts")

class Basket(SQLModel, table=True):
__tablename__ = "basket"

id: Optional[int] = Field(default=None, primary_key=True)
user_id: int = Field(foreign_key="users.id")
price: Decimal
status: BasketStatus = Field(
sa_column_kwargs={"nullable": False, "server_default": "Open"}
)

lines: List["BasketLine"] = Relationship(back_populates="basket")
order: Optional["Order"] = Relationship(back_populates="basket")

class BasketLine(SQLModel, table=True):
__tablename__ = 'basket_lines'

id: Optional[int] = Field(default=None, primary_key=True)
product_id: int = Field(foreign_key="products.id")
basket_id: int = Field(foreign_key="basket.id")
quantity: int
price: Decimal

product: Product = Relationship(back_populates="basket_lines")
basket: Basket = Relationship(back_populates="lines")

class Order(SQLModel, table=True):
__tablename__ = 'orders'

id: Optional[int] = Field(default=None, primary_key=True)
number: int = Field(
sa_column_kwargs={
"nullable": False,
"unique": True,
"server_default": "10000"
}
)
basket_id: int = Field(foreign_key="basket.id")
user_id: int = Field(foreign_key="users.id")
address_id: int = Field(foreign_key="addresses.id")
total_price: Decimal
shipping_price: Decimal
shipping_method: Optional[str] = None
status: OrderStatus = Field(
sa_column_kwargs={"nullable": False, "server_default": "Open"}
)
additional_info: Optional[str] = None
created_at: datetime = Field(default_factory=datetime.utcnow, nullable=False)

basket: Basket = Relationship(back_populates="order")
lines: List["OrderLine"] = Relationship(back_populates="order")

class OrderLine(SQLModel, table=True):
__tablename__ = 'order_lines'

id: Optional[int] = Field(default=None, primary_key=True)
product_id: int = Field(foreign_key="products.id")
order_id: int = Field(foreign_key="orders.id")
quantity: int
price: Decimal

product: Product = Relationship(back_populates="order_lines")
order: Order = Relationship(back_populates="lines")