65 lines
2.9 KiB
Python
65 lines
2.9 KiB
Python
from typing import List, Optional, TYPE_CHECKING
|
|
|
|
from sqlalchemy import Boolean, Integer, ForeignKey, Unicode, case, func, literal
|
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
from sqlalchemy.sql import expression as sql
|
|
|
|
from crudkit.core.base import Base, CRUDMixin
|
|
|
|
if TYPE_CHECKING:
|
|
from .room import Room
|
|
|
|
class User(Base, CRUDMixin):
|
|
__tablename__ = 'users'
|
|
|
|
first_name: Mapped[Optional[str]] = mapped_column(Unicode(255), nullable=True, index=True)
|
|
last_name: Mapped[Optional[str]] = mapped_column(Unicode(255), nullable=True, index=True)
|
|
title: Mapped[Optional[str]] = mapped_column(Unicode(255), nullable=True)
|
|
|
|
active: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=False, default=True, server_default=sql.true())
|
|
staff: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false())
|
|
|
|
image: Mapped[Optional['Image']] = relationship('Image', back_populates='user', passive_deletes=True)
|
|
image_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("images.id", ondelete="SET NULL"), nullable=True, index=True)
|
|
|
|
inventory: Mapped[List['Inventory']] = relationship('Inventory', back_populates='owner')
|
|
|
|
location: Mapped[Optional['Room']] = relationship('Room', back_populates='users')
|
|
location_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("rooms.id"), nullable=True, index=True)
|
|
|
|
supervisor: Mapped[Optional['User']] = relationship('User', back_populates='subordinates', remote_side='User.id')
|
|
supervisor_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("users.id"), nullable=True, index=True)
|
|
subordinates: Mapped[List['User']] = relationship('User', back_populates='supervisor')
|
|
|
|
work_logs: Mapped[Optional[List['WorkLog']]] = relationship('WorkLog', back_populates='contact')
|
|
|
|
is_deleted: Mapped[Boolean] = mapped_column(Boolean, nullable=False, default=False, server_default=sql.false())
|
|
|
|
def __repr__(self):
|
|
return f"<User(id={self.id}, first_name={repr(self.first_name)}, last_name={repr(self.last_name)})>"
|
|
|
|
@hybrid_property
|
|
def label(self):
|
|
out = f"{self.first_name} {self.last_name}"
|
|
if self.title:
|
|
out = out + f" ({self.title})"
|
|
return out
|
|
|
|
@label.expression
|
|
def label(cls):
|
|
first = func.coalesce(cls.first_name, "")
|
|
last = func.coalesce(cls.last_name, "")
|
|
title = func.coalesce(cls.title, "")
|
|
|
|
have_first = func.length(func.trim(first)) > 0
|
|
have_last = func.length(func.trim(last)) > 0
|
|
|
|
space = case((have_first & have_last, literal(" ")), else_=literal(""))
|
|
|
|
title_part = case(
|
|
(func.length(func.trim(title)) > 0, func.concat(" (", title, ")")),
|
|
else_=literal("")
|
|
)
|
|
|
|
return func.concat(first, space, last, title_part)
|