chore: baseline plantilla-proyectos como base del CRM
This commit is contained in:
0
backend/api/v1/modules/example/__init__.py
Normal file
0
backend/api/v1/modules/example/__init__.py
Normal file
21
backend/api/v1/modules/example/dto.py
Normal file
21
backend/api/v1/modules/example/dto.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class ItemCreate(BaseModel):
|
||||
name: str
|
||||
description: str | None = None
|
||||
|
||||
|
||||
class ItemUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
|
||||
|
||||
class ItemResponse(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
name: str
|
||||
description: str | None
|
||||
tenant_id: int
|
||||
company_id: int
|
||||
16
backend/api/v1/modules/example/models.py
Normal file
16
backend/api/v1/modules/example/models.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from sqlalchemy import Integer, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
|
||||
|
||||
class Item(Base, TenantScopedMixin, TimestampMixin):
|
||||
"""Modelo de ejemplo — renombra y ajusta a tu entidad de negocio."""
|
||||
|
||||
__tablename__ = "example_items"
|
||||
__table_args__ = {"schema": "public"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
65
backend/api/v1/modules/example/routes.py
Normal file
65
backend/api/v1/modules/example/routes.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from fastapi import APIRouter, Depends, Query, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.database import get_core_db
|
||||
from core.security import get_current_user
|
||||
|
||||
from .dto import ItemCreate, ItemResponse, ItemUpdate
|
||||
from . import service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/items", response_model=list[ItemResponse])
|
||||
def list_items(
|
||||
company_id: int = Query(..., description="Company ID"),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
db: Session = Depends(get_core_db),
|
||||
):
|
||||
tenant_id = current_user["tenant_id"]
|
||||
return service.get_items(db, tenant_id, company_id)
|
||||
|
||||
|
||||
@router.get("/items/{item_id}", response_model=ItemResponse)
|
||||
def get_item(
|
||||
item_id: int,
|
||||
company_id: int = Query(..., description="Company ID"),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
db: Session = Depends(get_core_db),
|
||||
):
|
||||
tenant_id = current_user["tenant_id"]
|
||||
return service.get_item(db, item_id, tenant_id, company_id)
|
||||
|
||||
|
||||
@router.post("/items", response_model=ItemResponse, status_code=status.HTTP_201_CREATED)
|
||||
def create_item(
|
||||
payload: ItemCreate,
|
||||
company_id: int = Query(..., description="Company ID"),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
db: Session = Depends(get_core_db),
|
||||
):
|
||||
tenant_id = current_user["tenant_id"]
|
||||
return service.create_item(db, payload, tenant_id, company_id)
|
||||
|
||||
|
||||
@router.patch("/items/{item_id}", response_model=ItemResponse)
|
||||
def update_item(
|
||||
item_id: int,
|
||||
payload: ItemUpdate,
|
||||
company_id: int = Query(..., description="Company ID"),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
db: Session = Depends(get_core_db),
|
||||
):
|
||||
tenant_id = current_user["tenant_id"]
|
||||
return service.update_item(db, item_id, payload, tenant_id, company_id)
|
||||
|
||||
|
||||
@router.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_item(
|
||||
item_id: int,
|
||||
company_id: int = Query(..., description="Company ID"),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
db: Session = Depends(get_core_db),
|
||||
):
|
||||
tenant_id = current_user["tenant_id"]
|
||||
service.delete_item(db, item_id, tenant_id, company_id)
|
||||
48
backend/api/v1/modules/example/service.py
Normal file
48
backend/api/v1/modules/example/service.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .dto import ItemCreate, ItemUpdate
|
||||
from .models import Item
|
||||
|
||||
|
||||
def get_items(db: Session, tenant_id: int, company_id: int) -> list[Item]:
|
||||
return (
|
||||
db.query(Item)
|
||||
.filter(Item.tenant_id == tenant_id, Item.company_id == company_id, Item.deleted_at.is_(None))
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def get_item(db: Session, item_id: int, tenant_id: int, company_id: int) -> Item:
|
||||
item = (
|
||||
db.query(Item)
|
||||
.filter(Item.id == item_id, Item.tenant_id == tenant_id, Item.company_id == company_id, Item.deleted_at.is_(None))
|
||||
.first()
|
||||
)
|
||||
if not item:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item no encontrado")
|
||||
return item
|
||||
|
||||
|
||||
def create_item(db: Session, payload: ItemCreate, tenant_id: int, company_id: int) -> Item:
|
||||
item = Item(**payload.model_dump(), tenant_id=tenant_id, company_id=company_id)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
db.refresh(item)
|
||||
return item
|
||||
|
||||
|
||||
def update_item(db: Session, item_id: int, payload: ItemUpdate, tenant_id: int, company_id: int) -> Item:
|
||||
item = get_item(db, item_id, tenant_id, company_id)
|
||||
for field, value in payload.model_dump(exclude_unset=True).items():
|
||||
setattr(item, field, value)
|
||||
db.commit()
|
||||
db.refresh(item)
|
||||
return item
|
||||
|
||||
|
||||
def delete_item(db: Session, item_id: int, tenant_id: int, company_id: int) -> None:
|
||||
item = get_item(db, item_id, tenant_id, company_id)
|
||||
from datetime import datetime, timezone
|
||||
item.deleted_at = datetime.now(timezone.utc)
|
||||
db.commit()
|
||||
Reference in New Issue
Block a user