From afa1b249ae057f646815694a6ac01d29c3d9ce6e Mon Sep 17 00:00:00 2001 From: Saurab-Shrestha Date: Tue, 20 Feb 2024 18:57:02 +0545 Subject: [PATCH] Added department models --- .../users/api/v1/routers/departments.py | 127 ++++++++++++++++++ private_gpt/users/crud/__init__.py | 3 +- private_gpt/users/crud/department_crud.py | 16 +++ private_gpt/users/models/__init__.py | 3 +- private_gpt/users/models/company.py | 3 +- private_gpt/users/models/department.py | 17 +++ private_gpt/users/models/documents.py | 5 + private_gpt/users/models/user.py | 4 + private_gpt/users/schemas/__init__.py | 3 +- private_gpt/users/schemas/company.py | 19 ++- private_gpt/users/schemas/deparment.py | 26 ++++ private_gpt/users/schemas/user.py | 4 +- 12 files changed, 219 insertions(+), 11 deletions(-) create mode 100644 private_gpt/users/api/v1/routers/departments.py create mode 100644 private_gpt/users/crud/department_crud.py create mode 100644 private_gpt/users/models/department.py create mode 100644 private_gpt/users/schemas/deparment.py diff --git a/private_gpt/users/api/v1/routers/departments.py b/private_gpt/users/api/v1/routers/departments.py new file mode 100644 index 00000000..d952c6e9 --- /dev/null +++ b/private_gpt/users/api/v1/routers/departments.py @@ -0,0 +1,127 @@ +from typing import Any, List + +from sqlalchemy.orm import Session +from fastapi.responses import JSONResponse +from fastapi.encoders import jsonable_encoder +from fastapi import APIRouter, Depends, HTTPException, status, Security + +from private_gpt.users.api import deps +from private_gpt.users.constants.role import Role +from private_gpt.users import crud, models, schemas + + +router = APIRouter(prefix="/departments", tags=["Deparments"]) + + +@router.get("", response_model=List[schemas.Department]) +def list_deparments( + db: Session = Depends(deps.get_db), + skip: int = 0, + limit: int = 100, + current_user: models.User = Security( + deps.get_current_user, + scopes=[Role.SUPER_ADMIN["name"]], + ), +) -> List[schemas.Department]: + """ + Retrieve a list of companies with pagination support. + """ + deparments = crud.deparment.get_multi(db, skip=skip, limit=limit) + return deparments + + +@router.post("/create", response_model=schemas.Department) +def create_deparment( + company_in: schemas.DepartmentCreate, + db: Session = Depends(deps.get_db), + current_user: models.User = Security( + deps.get_current_user, + scopes=[Role.SUPER_ADMIN["name"]], + ), +) -> schemas.Company: + """ + Create a new company + """ + deparment = crud.deparment.create(db=db, obj_in=company_in) + deparment = jsonable_encoder(deparment) + + return JSONResponse( + status_code=status.HTTP_201_CREATED, + content={ + "message": "Department created successfully", + "department": deparment + }, + ) + + +@router.get("/{deparment_id}", response_model=schemas.Department) +def read_company( + deparment_id: int, + db: Session = Depends(deps.get_db), + current_user: models.User = Security( + deps.get_current_user, + scopes=[Role.SUPER_ADMIN["name"]], + ), +) -> schemas.Company: + """ + Read a company by ID + """ + deparment = crud.deparment.get_by_id(db, id=deparment_id) + if deparment is None: + raise HTTPException(status_code=404, detail="Deparment not found") + return deparment + + +@router.put("/{deparment_id}", response_model=schemas.Department) +def update_company( + deparment_id: int, + deparment_in: schemas.DepartmentUpdate, + db: Session = Depends(deps.get_db), + current_user: models.User = Security( + deps.get_current_user, + scopes=[Role.SUPER_ADMIN["name"]], + ), +) -> schemas.Company: + """ + Update a company by ID + """ + deparment = crud.deparment.get_by_id(db, id=deparment_id) + if deparment is None: + raise HTTPException(status_code=404, detail="Deparment not found") + + updated_deparment = crud.deparment.update( + db=db, db_obj=deparment, obj_in=deparment_in) + updated_deparment = jsonable_encoder(updated_deparment) + return JSONResponse( + status_code=status.HTTP_200_OK, + content={ + "message": f"{deparment_in} Deparment updated successfully", + "deparment": updated_deparment + }, + ) + + +@router.delete("/{deparment_id}", response_model=schemas.Department) +def delete_company( + deparment_id: int, + db: Session = Depends(deps.get_db), + current_user: models.User = Security( + deps.get_current_user, + scopes=[Role.SUPER_ADMIN["name"]], + ), +) -> schemas.Company: + """ + Delete a company by ID + """ + + deparment = crud.deparment.remove(db=db, id=deparment_id) + if deparment is None: + raise HTTPException(status_code=404, detail="Deparment not found") + deparment = jsonable_encoder(deparment) + return JSONResponse( + status_code=status.HTTP_200_OK, + content={ + "message": "Deparment deleted successfully", + "deparment": deparment + }, + ) diff --git a/private_gpt/users/crud/__init__.py b/private_gpt/users/crud/__init__.py index aa2271b9..2131bab5 100644 --- a/private_gpt/users/crud/__init__.py +++ b/private_gpt/users/crud/__init__.py @@ -3,4 +3,5 @@ from .user_crud import user from .user_role_crud import user_role from .company_crud import company from .subscription_crud import subscription -from .document_crud import documents \ No newline at end of file +from .document_crud import documents +from .department_crud import deparment \ No newline at end of file diff --git a/private_gpt/users/crud/department_crud.py b/private_gpt/users/crud/department_crud.py new file mode 100644 index 00000000..b3c6e244 --- /dev/null +++ b/private_gpt/users/crud/department_crud.py @@ -0,0 +1,16 @@ +from sqlalchemy.orm import Session +from private_gpt.users.schemas.deparment import DepartmentCreate, DepartmentUpdate +from private_gpt.users.models.department import Department +from private_gpt.users.crud.base import CRUDBase +from typing import Optional + + +class CRUDDepartments(CRUDBase[Department, DepartmentCreate, DepartmentUpdate]): + def get_by_id(self, db: Session, *, id: str) -> Optional[Department]: + return db.query(self.model).filter(Department.id == id).first() + + def get_by_deparment_name(self, db: Session, *, name: str) -> Optional[Department]: + return db.query(self.model).filter(Department.name == name).first() + + +deparment = CRUDDepartments(Department) diff --git a/private_gpt/users/models/__init__.py b/private_gpt/users/models/__init__.py index 46bb9201..e899db28 100644 --- a/private_gpt/users/models/__init__.py +++ b/private_gpt/users/models/__init__.py @@ -3,4 +3,5 @@ from .company import Company from .user_role import UserRole from .role import Role from .documents import Documents -from .subscription import Subscription \ No newline at end of file +from .subscription import Subscription +from .department import Department \ No newline at end of file diff --git a/private_gpt/users/models/company.py b/private_gpt/users/models/company.py index 3c9adf41..eec834a0 100644 --- a/private_gpt/users/models/company.py +++ b/private_gpt/users/models/company.py @@ -14,4 +14,5 @@ class Company(Base): subscriptions = relationship("Subscription", back_populates="company") users = relationship("User", back_populates="company") - user_roles = relationship("UserRole", back_populates="company") \ No newline at end of file + user_roles = relationship("UserRole", back_populates="company") + departments = relationship("Department", back_populates="company") \ No newline at end of file diff --git a/private_gpt/users/models/department.py b/private_gpt/users/models/department.py new file mode 100644 index 00000000..22057b6d --- /dev/null +++ b/private_gpt/users/models/department.py @@ -0,0 +1,17 @@ +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship +from sqlalchemy import Column, Integer, String + +from private_gpt.users.db.base_class import Base + + +class Department(Base): + """Models a Department table.""" + + __tablename__ = "departments" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True, unique=True) + + company_id = Column(Integer, ForeignKey('companies.id')) + company = relationship("Company", back_populates="departments") diff --git a/private_gpt/users/models/documents.py b/private_gpt/users/models/documents.py index 5970fd55..739a4f64 100644 --- a/private_gpt/users/models/documents.py +++ b/private_gpt/users/models/documents.py @@ -21,3 +21,8 @@ class Documents(Base): ) uploaded_by_user = relationship( "User", back_populates="uploaded_documents") + department_id = Column(Integer, ForeignKey("departments.id"), nullable=True) + + uploaded_by_user = relationship( + "User", back_populates="uploaded_documents") + department = relationship("Department", back_populates="documents") diff --git a/private_gpt/users/models/user.py b/private_gpt/users/models/user.py index 6243ebc0..6d98a625 100644 --- a/private_gpt/users/models/user.py +++ b/private_gpt/users/models/user.py @@ -39,6 +39,10 @@ class User(Base): uploaded_documents = relationship("Documents", back_populates="uploaded_by_user") user_role = relationship( "UserRole", back_populates="user", uselist=False, cascade="all, delete-orphan") + + department_id = Column(Integer, ForeignKey( + "departments.id"), nullable=True) + department = relationship("Department", back_populates="users") def __repr__(self): """Returns string representation of model instance""" diff --git a/private_gpt/users/schemas/__init__.py b/private_gpt/users/schemas/__init__.py index 6763d498..06cd60b1 100644 --- a/private_gpt/users/schemas/__init__.py +++ b/private_gpt/users/schemas/__init__.py @@ -4,4 +4,5 @@ from .user import User, UserCreate, UserInDB, UserUpdate, UserBaseSchema, Profil from .user_role import UserRole, UserRoleCreate, UserRoleInDB, UserRoleUpdate from .subscription import Subscription, SubscriptionBase, SubscriptionCreate, SubscriptionUpdate from .company import Company, CompanyBase, CompanyCreate, CompanyUpdate -from .documents import Document, DocumentCreate, DocumentsBase, DocumentUpdate \ No newline at end of file +from .documents import Document, DocumentCreate, DocumentsBase, DocumentUpdate +from .deparment import Department, DepartmentCreate, DepartmentUpdate \ No newline at end of file diff --git a/private_gpt/users/schemas/company.py b/private_gpt/users/schemas/company.py index 6c1d7b3b..8ab79e47 100644 --- a/private_gpt/users/schemas/company.py +++ b/private_gpt/users/schemas/company.py @@ -1,19 +1,30 @@ from typing import List -from datetime import datetime from pydantic import BaseModel +from private_gpt.users.schemas import Department, User + + class CompanyBase(BaseModel): name: str + class CompanyCreate(CompanyBase): pass + class CompanyUpdate(CompanyBase): pass -class Company(CompanyBase): +class CompanyInDB(CompanyBase): id: int - + class Config: - orm_mode = True \ No newline at end of file + orm_mode = True + + +class Company(CompanyInDB): + subscriptions: List[str] = [] + users: List[User] = [] + user_roles: List[str] = [] + departments: List[Department] = [] diff --git a/private_gpt/users/schemas/deparment.py b/private_gpt/users/schemas/deparment.py new file mode 100644 index 00000000..d2ad3c1b --- /dev/null +++ b/private_gpt/users/schemas/deparment.py @@ -0,0 +1,26 @@ +from typing import List +from pydantic import BaseModel + + +class DepartmentBase(BaseModel): + name: str + + +class DepartmentCreate(DepartmentBase): + pass + + +class DepartmentUpdate(DepartmentBase): + pass + + +class DepartmentInDB(DepartmentBase): + id: int + company_id: int + + class Config: + orm_mode = True + + +class Department(DepartmentInDB): + pass diff --git a/private_gpt/users/schemas/user.py b/private_gpt/users/schemas/user.py index 05ad7aaf..41dbd240 100644 --- a/private_gpt/users/schemas/user.py +++ b/private_gpt/users/schemas/user.py @@ -47,14 +47,11 @@ class UserSchema(UserBaseSchema): class Config: orm_mode = True -# Additional properties to return via API class User(UserSchema): pass -# Additional properties stored in DB - class UserInDB(UserSchema): hashed_password: str @@ -72,3 +69,4 @@ class UserAdminUpdate(BaseModel): id: int fullname: str role: str + department_id: Optional[int] = None