updated to use 2 apis
This commit is contained in:
Binary file not shown.
@@ -1,2 +1,7 @@
|
||||
class UserAlreadyExists(Exception):
|
||||
pass
|
||||
class OrderNotFound(Exception):
|
||||
pass
|
||||
|
||||
class OrderAlreadyExists(Exception):
|
||||
pass
|
||||
Binary file not shown.
23
src/application/ports/order_repository.py
Normal file
23
src/application/ports/order_repository.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from domain.orders import Order
|
||||
|
||||
class OrderRepository(ABC):
|
||||
@abstractmethod
|
||||
def save(self, order: Order):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def viewAll(self) -> list[Order]:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def viewById(self, order_id: int):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def removeOrder(self, order_id: int):
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def editOrder(self, order_id: int, order: Order):
|
||||
...
|
||||
Binary file not shown.
68
src/application/services/order_services.py
Normal file
68
src/application/services/order_services.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from domain.orders import Order
|
||||
from application.ports.order_repository import OrderRepository
|
||||
|
||||
class CreateOrder:
|
||||
def __init__(self, repo: OrderRepository):
|
||||
if not isinstance(repo, OrderRepository):
|
||||
raise TypeError("repo must implement OrderRepository")
|
||||
self.repo = repo
|
||||
|
||||
def execute(self, user_id: int, description: str, quantity: int, total_price: float):
|
||||
from datetime import datetime
|
||||
order = Order(
|
||||
order_id=0,
|
||||
user_id=user_id,
|
||||
description=description,
|
||||
quantity=quantity,
|
||||
total_price=total_price,
|
||||
created_at=datetime.now()
|
||||
)
|
||||
self.repo.save(order)
|
||||
return order
|
||||
|
||||
class ViewOrders:
|
||||
def __init__(self, repo: OrderRepository):
|
||||
if not isinstance(repo, OrderRepository):
|
||||
raise TypeError("repo must implement OrderRepository")
|
||||
self.repo = repo
|
||||
|
||||
def execute(self):
|
||||
orders = self.repo.viewAll()
|
||||
return orders
|
||||
|
||||
class ViewOrderById:
|
||||
def __init__(self, repo: OrderRepository):
|
||||
if not isinstance(repo, OrderRepository):
|
||||
raise TypeError("repo must implement OrderRepository")
|
||||
self.repo = repo
|
||||
|
||||
def execute(self, order_id: int) -> Order | None:
|
||||
order = self.repo.viewById(order_id)
|
||||
return order
|
||||
|
||||
class RemoveOrderById:
|
||||
def __init__(self, repo: OrderRepository):
|
||||
if not isinstance(repo, OrderRepository):
|
||||
raise TypeError("repo must implement OrderRepository")
|
||||
self.repo = repo
|
||||
|
||||
def execute(self, order_id: int) -> Order:
|
||||
order = self.repo.removeOrder(order_id)
|
||||
return {"Result": f"Order {order_id} deleted succesfully"}
|
||||
|
||||
class EditOrderById:
|
||||
def __init__(self, repo: OrderRepository):
|
||||
if not isinstance(repo, OrderRepository):
|
||||
raise TypeError("repo must implement OrderRepository")
|
||||
self.repo = repo
|
||||
|
||||
def execute(self, order_id: int, user_id: int, description: str, quantity: int, total_price: float) -> Order | None:
|
||||
order = Order(
|
||||
order_id=order_id,
|
||||
user_id=user_id,
|
||||
description=description,
|
||||
quantity=quantity,
|
||||
total_price=total_price,
|
||||
created_at=None
|
||||
)
|
||||
return self.repo.editOrder(order_id, order)
|
||||
BIN
src/domain/__pycache__/orders.cpython-314.pyc
Normal file
BIN
src/domain/__pycache__/orders.cpython-314.pyc
Normal file
Binary file not shown.
11
src/domain/orders.py
Normal file
11
src/domain/orders.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
@dataclass
|
||||
class Order:
|
||||
order_id: int
|
||||
user_id: int
|
||||
description: str
|
||||
quantity: int
|
||||
total_price: float
|
||||
created_at: datetime
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
from sqlalchemy import Column, Integer, String
|
||||
from sqlalchemy import Column, Integer, String, Float, DateTime
|
||||
from infrastructure.adapters.persistence.db import Base
|
||||
|
||||
class UserModel(Base):
|
||||
@@ -8,3 +8,13 @@ class UserModel(Base):
|
||||
name = Column(String, unique=False, index=True)
|
||||
email = Column(String, unique=True, index=True)
|
||||
phone = Column(String, unique=True, index=True)
|
||||
|
||||
class OrderModel(Base):
|
||||
__tablename__ = "orders"
|
||||
|
||||
order_id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, index=True)
|
||||
description = Column(String, index=True)
|
||||
quantity = Column(Integer, index=True)
|
||||
total_price = Column(Float, index=True)
|
||||
created_at = Column(DateTime, index=True)
|
||||
|
||||
108
src/infrastructure/adapters/persistence/order_repository_sql.py
Normal file
108
src/infrastructure/adapters/persistence/order_repository_sql.py
Normal file
@@ -0,0 +1,108 @@
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from domain.orders import Order
|
||||
from application.ports.order_repository import OrderRepository
|
||||
from infrastructure.adapters.persistence.db import SessionLocal
|
||||
from infrastructure.adapters.persistence.models import OrderModel
|
||||
|
||||
class SqlOrderRepository(OrderRepository):
|
||||
def __init__(self):
|
||||
self.db: Session = SessionLocal()
|
||||
|
||||
def save(self, order: Order):
|
||||
model = OrderModel(
|
||||
user_id=order.user_id,
|
||||
description=order.description,
|
||||
quantity=order.quantity,
|
||||
total_price=order.total_price,
|
||||
created_at=order.created_at
|
||||
)
|
||||
|
||||
self.db.add(model)
|
||||
|
||||
try:
|
||||
self.db.commit()
|
||||
except IntegrityError:
|
||||
self.db.rollback()
|
||||
raise Exception("An error occurred while creating the order.")
|
||||
|
||||
self.db.refresh(model)
|
||||
|
||||
return Order(
|
||||
order_id=model.order_id,
|
||||
user_id=model.user_id,
|
||||
description=model.description,
|
||||
quantity=model.quantity,
|
||||
total_price=model.total_price,
|
||||
created_at=model.created_at
|
||||
)
|
||||
|
||||
def viewAll(self) -> list[Order]:
|
||||
models = self.db.query(OrderModel).all()
|
||||
|
||||
return [
|
||||
Order(
|
||||
order_id=model.order_id,
|
||||
user_id=model.user_id,
|
||||
description=model.description,
|
||||
quantity=model.quantity,
|
||||
total_price=model.total_price,
|
||||
created_at=model.created_at
|
||||
) for model in models
|
||||
]
|
||||
|
||||
def viewById(self, order_id: int) -> Order | None:
|
||||
model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first()
|
||||
|
||||
if not model:
|
||||
return None
|
||||
|
||||
return Order(
|
||||
order_id=model.order_id,
|
||||
user_id=model.user_id,
|
||||
description=model.description,
|
||||
quantity=model.quantity,
|
||||
total_price=model.total_price,
|
||||
created_at=model.created_at
|
||||
)
|
||||
|
||||
def removeOrder(self, order_id: int):
|
||||
model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first()
|
||||
|
||||
if not model:
|
||||
return False
|
||||
|
||||
try:
|
||||
self.db.delete(model)
|
||||
self.db.commit()
|
||||
return True
|
||||
except IntegrityError:
|
||||
self.db.rollback()
|
||||
raise Exception("Cannot delete order due to existing references.")
|
||||
|
||||
def editOrder(self, order_id: int, order: Order) -> Order | None:
|
||||
model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first()
|
||||
|
||||
if not model:
|
||||
return None
|
||||
|
||||
try:
|
||||
model.user_id = order.user_id
|
||||
model.description = order.description
|
||||
model.quantity = order.quantity
|
||||
model.total_price = order.total_price
|
||||
|
||||
self.db.commit()
|
||||
self.db.refresh(model)
|
||||
|
||||
return Order(
|
||||
order_id=model.order_id,
|
||||
user_id=model.user_id,
|
||||
description=model.description,
|
||||
quantity=model.quantity,
|
||||
total_price=model.total_price,
|
||||
created_at=model.created_at
|
||||
)
|
||||
except IntegrityError:
|
||||
self.db.rollback()
|
||||
raise Exception("An error occurred while updating the order.")
|
||||
0
src/infrastructure/api/orders/__init__.py
Normal file
0
src/infrastructure/api/orders/__init__.py
Normal file
Binary file not shown.
BIN
src/infrastructure/api/orders/__pycache__/app.cpython-314.pyc
Normal file
BIN
src/infrastructure/api/orders/__pycache__/app.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/infrastructure/api/orders/__pycache__/orders.cpython-314.pyc
Normal file
BIN
src/infrastructure/api/orders/__pycache__/orders.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/infrastructure/api/orders/__pycache__/root.cpython-314.pyc
Normal file
BIN
src/infrastructure/api/orders/__pycache__/root.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/infrastructure/api/orders/__pycache__/router.cpython-314.pyc
Normal file
BIN
src/infrastructure/api/orders/__pycache__/router.cpython-314.pyc
Normal file
Binary file not shown.
10
src/infrastructure/api/orders/app.py
Normal file
10
src/infrastructure/api/orders/app.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from fastapi import FastAPI
|
||||
from core.config import ConfSettings
|
||||
from infrastructure.api.orders.router import router
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
app = FastAPI(title="Orders Microservice",
|
||||
version="1.0.0",
|
||||
description="Microservicio de gestión de pedidos")
|
||||
app.include_router(router)
|
||||
return app
|
||||
77
src/infrastructure/api/orders/orders.py
Normal file
77
src/infrastructure/api/orders/orders.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from application.services.order_services import CreateOrder, ViewOrders, ViewOrderById, RemoveOrderById, EditOrderById
|
||||
from infrastructure.adapters.persistence.order_repository_sql import SqlOrderRepository
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/")
|
||||
def create_order(user_id: int, description: str, quantity: int, total_price: float):
|
||||
service = CreateOrder(SqlOrderRepository())
|
||||
|
||||
try:
|
||||
return service.execute(user_id, description, quantity, total_price)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=str(e)
|
||||
)
|
||||
|
||||
@router.get("/")
|
||||
def view_all_orders():
|
||||
service = ViewOrders(SqlOrderRepository())
|
||||
|
||||
try:
|
||||
return service.execute()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=str(e)
|
||||
)
|
||||
|
||||
@router.get("/{order_id}")
|
||||
def view_order_by_id(order_id: int):
|
||||
service = ViewOrderById(SqlOrderRepository())
|
||||
|
||||
result = service.execute(order_id)
|
||||
|
||||
if result is None:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Order not found"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@router.delete("/{order_id}")
|
||||
def delete_order_by_id(order_id: int):
|
||||
service = RemoveOrderById(SqlOrderRepository())
|
||||
|
||||
result = service.execute(order_id)
|
||||
|
||||
if result is None:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Order not found"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@router.put("/{order_id}")
|
||||
def edit_order_by_id(order_id: int, user_id: int, description: str, quantity: int, total_price: float):
|
||||
service = EditOrderById(SqlOrderRepository())
|
||||
|
||||
try:
|
||||
result = service.execute(order_id=order_id, user_id=user_id, description=description, quantity=quantity, total_price=total_price)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=str(e)
|
||||
)
|
||||
|
||||
if result is None:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Order not found"
|
||||
)
|
||||
|
||||
return result
|
||||
16
src/infrastructure/api/orders/root.py
Normal file
16
src/infrastructure/api/orders/root.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from fastapi import APIRouter
|
||||
import platform
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/")
|
||||
def root():
|
||||
uname = platform.uname()
|
||||
return {
|
||||
"machine": {
|
||||
"OS": f"{uname.system} {uname.release}",
|
||||
"Arch": uname.machine
|
||||
},
|
||||
"Status": "Running",
|
||||
"Docs": "/docs"
|
||||
}
|
||||
17
src/infrastructure/api/orders/router.py
Normal file
17
src/infrastructure/api/orders/router.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from fastapi import APIRouter
|
||||
from infrastructure.api.orders.orders import router as orders_router
|
||||
from infrastructure.api.orders.root import router as root_router
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(
|
||||
orders_router,
|
||||
prefix="/orders",
|
||||
tags=["orders"]
|
||||
)
|
||||
|
||||
router.include_router(
|
||||
root_router,
|
||||
prefix='',
|
||||
tags=["root"]
|
||||
)
|
||||
51
src/main.py
51
src/main.py
@@ -1,17 +1,52 @@
|
||||
from infrastructure.api.users.app import create_app
|
||||
from infrastructure.api.users.app import create_app as create_users_app
|
||||
from infrastructure.api.orders.app import create_app as create_orders_app
|
||||
from core.config import ConfSettings
|
||||
import threading
|
||||
import uvicorn
|
||||
|
||||
app = create_app()
|
||||
|
||||
def run():
|
||||
import uvicorn
|
||||
def run_users_api():
|
||||
"""Ejecuta la API de usuarios en puerto 8000"""
|
||||
app_users = create_users_app()
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
app_users,
|
||||
host=ConfSettings.host,
|
||||
port=ConfSettings.port,
|
||||
reload=ConfSettings.reload,
|
||||
port=8000,
|
||||
reload=False,
|
||||
log_level=ConfSettings.log_level,
|
||||
)
|
||||
|
||||
def run_orders_api():
|
||||
"""Ejecuta la API de pedidos en puerto 8001"""
|
||||
app_orders = create_orders_app()
|
||||
uvicorn.run(
|
||||
app_orders,
|
||||
host=ConfSettings.host,
|
||||
port=8001,
|
||||
reload=False,
|
||||
log_level=ConfSettings.log_level,
|
||||
)
|
||||
|
||||
def run():
|
||||
"""Inicia ambas APIs en threads separados"""
|
||||
print("Iniciando microservicios...")
|
||||
|
||||
users_thread = threading.Thread(target=run_users_api, daemon=True, name="Users-API")
|
||||
orders_thread = threading.Thread(target=run_orders_api, daemon=True, name="Orders-API")
|
||||
|
||||
users_thread.start()
|
||||
orders_thread.start()
|
||||
|
||||
print("✓ API de Usuarios ejecutándose en http://0.0.0.0:8000")
|
||||
print("✓ API de Pedidos ejecutándose en http://0.0.0.0:8001")
|
||||
print("\nDocumentación disponible en:")
|
||||
print(" - Usuarios: http://localhost:8000/docs")
|
||||
print(" - Pedidos: http://localhost:8001/docs")
|
||||
|
||||
try:
|
||||
users_thread.join()
|
||||
orders_thread.join()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nAteniendo señal de salida...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
17
src/main_orders.py
Normal file
17
src/main_orders.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from infrastructure.api.orders.app import create_app
|
||||
from core.config import ConfSettings
|
||||
|
||||
app = create_app()
|
||||
|
||||
def run():
|
||||
import uvicorn
|
||||
uvicorn.run(
|
||||
"main_orders:app",
|
||||
host=ConfSettings.host,
|
||||
port=8001,
|
||||
reload=ConfSettings.reload,
|
||||
log_level=ConfSettings.log_level,
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
BIN
src/users.db
BIN
src/users.db
Binary file not shown.
Reference in New Issue
Block a user