import uuid from datetime import datetime from brewman.models.master import Product from sqlalchemy import ( Boolean, Column, Date, DateTime, ForeignKey, Integer, Numeric, Unicode, UniqueConstraint, ) from sqlalchemy.dialects.postgresql import BYTEA, UUID from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import Session, backref, relationship, synonym from .meta import Base class VoucherType: def __init__(self, id_, name): self.id = id_ self.name = name @classmethod def list(cls): list_ = [ VoucherType(1, "Journal"), VoucherType(2, "Purchase"), VoucherType(3, "Issue"), VoucherType(4, "Payment"), VoucherType(5, "Receipt"), VoucherType(6, "Purchase Return"), VoucherType(7, "Opening Accounts"), VoucherType(8, "Opening Batches"), VoucherType(9, "Verification"), VoucherType(10, "Opening Balance"), VoucherType(11, "Closing Balance"), VoucherType(12, "Employee Benefit"), VoucherType(13, "Incentive"), ] return list_ @classmethod def by_name(cls, name): list_ = cls.list() for item in list_: if item.name == name: return item @classmethod def by_id(cls, id_): list_ = cls.list() for item in list_: if item.id == id_: return item class Voucher(Base): __tablename__ = "vouchers" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) date = Column("date", Date, nullable=False, index=True) narration = Column("narration", Unicode(1000), nullable=False) is_reconciled = Column("is_reconciled", Boolean, nullable=False) reconcile_date = Column("reconcile_date", Date, nullable=False) is_starred = Column("is_starred", Boolean, nullable=False) creation_date = Column("creation_date", DateTime(timezone=True), nullable=False) last_edit_date = Column("last_edit_date", DateTime(timezone=True), nullable=False) _type = Column("voucher_type", Integer, nullable=False) user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("auth_users.id"), nullable=False) posted = Column("is_posted", Boolean, nullable=False) poster_id = Column("poster_id", UUID(as_uuid=True), ForeignKey("auth_users.id")) user = relationship("User", primaryjoin="User.id==Voucher.user_id", cascade=None) poster = relationship("User", primaryjoin="User.id==Voucher.poster_id", cascade=None) journals = relationship( "Journal", back_populates="voucher", cascade="delete, delete-orphan", cascade_backrefs=False, ) inventories = relationship( "Inventory", back_populates="voucher", cascade="delete, delete-orphan", cascade_backrefs=False, ) employee_benefits = relationship( "EmployeeBenefit", backref="voucher", cascade="delete, delete-orphan", cascade_backrefs=False, ) incentives = relationship( "Incentive", backref="voucher", cascade="delete, delete-orphan", cascade_backrefs=False, ) def _get_type(self): return self._type # for item in VoucherType.list(): # if self._type == item.id: # return item def _set_type(self, value): if type(value) == int: self._type = value else: self._type = value.id type = property(_get_type, _set_type) type = synonym("_type", descriptor=type) def __init__( self, date=None, is_reconciled=False, reconcile_date=None, is_starred=None, narration="", posted=False, creation_date=None, last_edit_date=None, type_=None, user_id=None, poster_id=None, ): self.date = date self.is_reconciled = is_reconciled self.reconcile_date = reconcile_date or date self.is_starred = is_starred if is_starred is not None else False self.narration = narration self.posted = posted self.creation_date = creation_date or datetime.utcnow() self.last_edit_date = last_edit_date or datetime.utcnow() self.type = type_ self.user_id = user_id self.poster_id = poster_id class Journal(Base): __tablename__ = "journals" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) debit = Column("debit", Integer, nullable=False) amount = Column("amount", Numeric(precision=15, scale=2), nullable=False) voucher_id = Column( "voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, index=True, ) account_id = Column("account_id", UUID(as_uuid=True), ForeignKey("accounts.id"), nullable=False) cost_centre_id = Column( "cost_centre_id", UUID(as_uuid=True), ForeignKey("cost_centres.id"), nullable=False, ) voucher = relationship("Voucher", back_populates="journals") account = relationship("AccountBase", back_populates="journals") @hybrid_property def signed_amount(self): return self.debit * self.amount @property def __name__(self): return self.name def __init__( self, id_=None, debit=None, amount=None, voucher_id=None, account_id=None, cost_centre_id=None, ): self.id = id_ self.debit = debit self.amount = amount self.voucher_id = voucher_id self.account_id = account_id self.cost_centre_id = cost_centre_id class EmployeeBenefit(Base): __tablename__ = "employee_benefit" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False) journal_id = Column("journal_id", UUID(as_uuid=True), ForeignKey("journals.id"), nullable=False) gross_salary = Column("gross_salary", Integer) days_worked = Column("days_worked", Integer) esi_ee = Column("esi_employee", Integer) pf_ee = Column("pf_employee", Integer) esi_er = Column("esi_employer", Integer) pf_er = Column("pf_employer", Integer) journal = relationship( Journal, backref=backref("employee_benefit", uselist=False), cascade=None, cascade_backrefs=False, ) def __init__( self, id_=None, voucher_id=None, journal_id=None, journal=None, gross_salary=None, days_worked=None, esi_ee=None, pf_ee=None, esi_er=None, pf_er=None, ): self.id = id_ self.voucher_id = voucher_id self.gross_salary = gross_salary self.days_worked = days_worked self.esi_ee = esi_ee self.pf_ee = pf_ee self.esi_er = esi_er self.pf_er = pf_er if journal is None: self.journal_id = journal_id else: self.journal = journal class Incentive(Base): __tablename__ = "incentives" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False) journal_id = Column("journal_id", UUID(as_uuid=True), ForeignKey("journals.id"), nullable=False) days_worked = Column("days_worked", Numeric(precision=5, scale=1), nullable=False) points = Column("points", Numeric(precision=5, scale=2), nullable=False) journal = relationship( Journal, backref=backref("incentive", uselist=False), cascade=None, cascade_backrefs=False, ) def __init__( self, id_=None, voucher_id=None, journal_id=None, journal=None, days_worked=None, points=None, ): self.id = id_ self.voucher_id = voucher_id if journal is None: self.journal_id = journal_id else: self.journal = journal self.days_worked = days_worked self.points = points class Inventory(Base): __tablename__ = "inventories" __table_args__ = (UniqueConstraint("voucher_id", "batch_id"),) id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) voucher_id = Column( "voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, index=True, ) product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False) batch_id = Column("batch_id", UUID(as_uuid=True), ForeignKey("batches.id"), nullable=False) quantity = Column("quantity", Numeric(precision=15, scale=2), nullable=False) rate = Column("rate", Numeric(precision=15, scale=2), nullable=False) tax = Column("tax", Numeric(precision=15, scale=5), nullable=False) discount = Column("discount", Numeric(precision=15, scale=5), nullable=False) voucher = relationship("Voucher", back_populates="inventories") def __init__( self, id_=None, voucher_id=None, product_id=None, batch_id=None, quantity=None, rate=None, tax=None, discount=None, batch=None, product=None, ): self.id = id_ self.voucher_id = voucher_id if product is None: self.product_id = product_id else: self.product = product if batch is None: self.batch_id = batch_id else: self.batch = batch self.quantity = quantity self.rate = rate self.tax = tax self.discount = discount @hybrid_property def amount(self): return self.quantity * self.rate * (1 + self.tax) * (1 - self.discount) class Batch(Base): __tablename__ = "batches" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column("name", Date, nullable=False) product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False) quantity_remaining = Column("quantity_remaining", Numeric(precision=15, scale=2), nullable=False) rate = Column("rate", Numeric(precision=15, scale=2), nullable=False) tax = Column("tax", Numeric(precision=15, scale=5), nullable=False) discount = Column("discount", Numeric(precision=15, scale=5), nullable=False) inventories = relationship("Inventory", backref="batch", cascade=None, cascade_backrefs=False) def __init__( self, name=None, product_id=None, quantity_remaining=None, rate=None, tax=None, discount=None, product=None, ): self.name = name self.product_id = product_id self.quantity_remaining = quantity_remaining self.rate = rate self.tax = tax self.discount = discount if product is None: self.product_id = product_id else: self.product = product def amount(self): return self.quantity_remaining * self.rate * (1 + self.tax) * (1 - self.discount) @classmethod def list(cls, q, include_nil, date, db: Session): query = db.query(cls).join(cls.product) if not include_nil: query = query.filter(cls.quantity_remaining > 0) if date is not None: query = query.filter(cls.name <= date) if q is not None: for item in q.split(): query = query.filter(Product.name.ilike(f"%{item}%")) return query.order_by(Product.name).order_by(cls.name).all() @classmethod def suspense(cls): return uuid.UUID("a955790e-93cf-493c-a816-c7d92b127383") class Attendance(Base): __tablename__ = "attendances" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) employee_id = Column("employee_id", UUID(as_uuid=True), ForeignKey("employees.id")) date = Column("date", Date, nullable=False) attendance_type = Column("attendance_type", Integer) amount = Column("amount", Numeric(precision=5, scale=2)) creation_date = Column("creation_date", DateTime(timezone=True)) user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("auth_users.id")) is_valid = Column("is_valid", Boolean) user = relationship("User", primaryjoin="User.id==Attendance.user_id") def __init__( self, id_=None, employee_id=None, date=None, attendance_type=None, amount=None, creation_date=None, user_id=None, is_valid=None, ): self.id = id_ self.employee_id = employee_id self.date = date self.attendance_type = attendance_type self.amount = amount if amount is not None else 0 self.creation_date = creation_date or datetime.utcnow() self.user_id = user_id self.is_valid = is_valid if is_valid is not None else True def create(self, db: Session): old = ( db.query(Attendance) .filter(Attendance.date == self.date) .filter(Attendance.employee_id == self.employee_id) .filter(Attendance.is_valid == True) # noqa: E712 .first() ) if old is None or old.attendance_type != self.attendance_type: if old is not None: old.is_valid = False db.add(self) class Fingerprint(Base): __tablename__ = "fingerprints" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) employee_id = Column("employee_id", UUID(as_uuid=True), ForeignKey("employees.id")) date = Column("date", DateTime) def __init__(self, id_=None, employee_id=None, date=None): self.id = id_ self.employee_id = employee_id self.date = date self.fingerprint_type = 0 class DbImage(Base): __tablename__ = "images" id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) resource_id = Column("resource_id", UUID(as_uuid=True), nullable=False) resource_type = Column("resource_type", Unicode(255), nullable=False) image = Column("image", BYTEA, nullable=False) thumbnail = Column("thumbnail", BYTEA, nullable=False) creation_date = Column("creation_date", DateTime(timezone=True), nullable=False) def __init__( self, resource_id=None, resource_type=None, image=None, thumbnail=None, creation_date=None, id_=None, ): self.resource_id = resource_id self.resource_type = resource_type self.image = image self.thumbnail = thumbnail self.creation_date = creation_date or datetime.utcnow() self.id = id_