updated to use 2 apis

This commit is contained in:
2026-02-13 16:00:09 -06:00
parent 2c391d8e4a
commit 128ba9cc90
25 changed files with 407 additions and 10 deletions

View File

@@ -1,2 +1,7 @@
class UserAlreadyExists(Exception): class UserAlreadyExists(Exception):
pass pass
class OrderNotFound(Exception):
pass
class OrderAlreadyExists(Exception):
pass

View 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):
...

View 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)

Binary file not shown.

11
src/domain/orders.py Normal file
View 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

View File

@@ -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 from infrastructure.adapters.persistence.db import Base
class UserModel(Base): class UserModel(Base):
@@ -7,4 +7,14 @@ class UserModel(Base):
user_id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=False, index=True) name = Column(String, unique=False, index=True)
email = Column(String, unique=True, index=True) email = Column(String, unique=True, index=True)
phone = 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)

View 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.")

View 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

View 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

View 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"
}

View 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"]
)

View File

@@ -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 from core.config import ConfSettings
import threading
import uvicorn
app = create_app() def run_users_api():
"""Ejecuta la API de usuarios en puerto 8000"""
def run(): app_users = create_users_app()
import uvicorn
uvicorn.run( uvicorn.run(
"main:app", app_users,
host=ConfSettings.host, host=ConfSettings.host,
port=ConfSettings.port, port=8000,
reload=ConfSettings.reload, reload=False,
log_level=ConfSettings.log_level, 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__": if __name__ == "__main__":
run() run()

17
src/main_orders.py Normal file
View 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()

Binary file not shown.