Added: Rate Contract Module. To implement: Checking this during purchase.
This commit is contained in:
@ -5,10 +5,8 @@ Revises: ad8b2d208492
|
||||
Create Date: 2021-09-11 05:32:56.683107
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
|
||||
71
brewman/alembic/versions/071e8f29d257_rate_contracts.py
Normal file
71
brewman/alembic/versions/071e8f29d257_rate_contracts.py
Normal file
@ -0,0 +1,71 @@
|
||||
"""rate contracts
|
||||
|
||||
Revision ID: 071e8f29d257
|
||||
Revises: 0363f582ab28
|
||||
Create Date: 2021-09-11 05:57:49.062468
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
from brewman.models.permission import Permission
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
|
||||
revision = "071e8f29d257"
|
||||
down_revision = "0363f582ab28"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.execute(Permission.__table__.insert().values(id="f97589c6-df9f-45d3-874d-4245a4d99ade", name="Rate Contracts"))
|
||||
op.create_table(
|
||||
"rate_contracts",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("date", sa.Date(), nullable=False),
|
||||
sa.Column("vendor_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("valid_from", sa.Date(), nullable=True),
|
||||
sa.Column("valid_till", sa.Date(), nullable=True),
|
||||
sa.Column("narration", sa.Unicode(length=1000), nullable=False),
|
||||
sa.Column("user_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("creation_date", sa.DateTime(), nullable=False),
|
||||
sa.Column("last_edit_date", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["user_id"], ["users.id"], name=op.f("fk_rate_contracts_user_id_users")),
|
||||
sa.ForeignKeyConstraint(["vendor_id"], ["accounts.id"], name=op.f("fk_rate_contracts_vendor_id_accounts")),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_rate_contracts")),
|
||||
)
|
||||
op.create_index(op.f("ix_rate_contracts_date"), "rate_contracts", ["date"], unique=False)
|
||||
op.create_table(
|
||||
"rate_contract_items",
|
||||
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("rate_contract_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("product_id", postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column("cost_price", sa.Numeric(precision=15, scale=2), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["product_id"], ["products.id"], name=op.f("fk_rate_contract_items_product_id_products")
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["rate_contract_id"],
|
||||
["rate_contracts.id"],
|
||||
name=op.f("fk_rate_contract_items_rate_contract_id_rate_contracts"),
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_rate_contract_items")),
|
||||
sa.UniqueConstraint("rate_contract_id", "product_id", name=op.f("uq_rate_contract_items_rate_contract_id")),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_rate_contract_items_rate_contract_id"), "rate_contract_items", ["rate_contract_id"], unique=False
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f("ix_rate_contract_items_rate_contract_id"), table_name="rate_contract_items")
|
||||
op.drop_table("rate_contract_items")
|
||||
op.drop_index(op.f("ix_rate_contracts_date"), table_name="rate_contracts")
|
||||
op.drop_table("rate_contracts")
|
||||
# ### end Alembic commands ###
|
||||
@ -1,7 +1,7 @@
|
||||
"""Initial Commit
|
||||
|
||||
Revision ID: 0bf3d70ee7de
|
||||
Revises:
|
||||
Revises:
|
||||
Create Date: 2020-05-10 19:02:57.301086
|
||||
|
||||
"""
|
||||
|
||||
@ -273,7 +273,7 @@ def upgrade():
|
||||
)
|
||||
op.execute(permission.delete().where(permission.c.name.in_(["Payment", "Receipt"])))
|
||||
|
||||
### end Alembic commands ###
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
||||
@ -18,6 +18,8 @@ from ..models.login_history import LoginHistory # noqa: F401
|
||||
from ..models.permission import Permission # noqa: F401
|
||||
from ..models.product import Product # noqa: F401
|
||||
from ..models.product_group import ProductGroup # noqa: F401
|
||||
from ..models.rate_contract import RateContract # noqa: F401
|
||||
from ..models.rate_contract_item import RateContractItem # noqa: F401
|
||||
from ..models.recipe import Recipe # noqa: F401
|
||||
from ..models.recipe_item import RecipeItem # noqa: F401
|
||||
from ..models.role import Role # noqa: F401
|
||||
|
||||
@ -33,6 +33,7 @@ from .routers import (
|
||||
product_group,
|
||||
purchase,
|
||||
purchase_return,
|
||||
rate_contract,
|
||||
rebase,
|
||||
recipe,
|
||||
reset_stock,
|
||||
@ -76,6 +77,7 @@ app.include_router(attendance_types.router, prefix="/api/attendance-types", tags
|
||||
app.include_router(employee_attendance.router, prefix="/api/employee-attendance", tags=["attendance"])
|
||||
app.include_router(employee_attendance.router, prefix="/api/employee-attendance", tags=["attendance"])
|
||||
app.include_router(attendance_report.router, prefix="/attendance-report", tags=["attendance"])
|
||||
app.include_router(rate_contract.router, prefix="/api/rate-contracts", tags=["products"])
|
||||
|
||||
app.include_router(cost_centre.router, prefix="/api/cost-centres", tags=["cost-centres"])
|
||||
app.include_router(employee.router, prefix="/api/employees", tags=["employees"])
|
||||
|
||||
@ -32,6 +32,8 @@ class AccountBase(Base):
|
||||
journals = relationship("Journal", back_populates="account")
|
||||
cost_centre = relationship("CostCentre", back_populates="accounts")
|
||||
|
||||
rate_contracts = relationship("RateContract", back_populates="vendor")
|
||||
|
||||
@property
|
||||
def __name__(self):
|
||||
return self.name
|
||||
|
||||
@ -1,124 +1,50 @@
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
Column,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
Numeric,
|
||||
Unicode,
|
||||
UniqueConstraint,
|
||||
case,
|
||||
func,
|
||||
select,
|
||||
)
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column, Date, DateTime, ForeignKey, Unicode
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
from sqlalchemy.orm import Session, relationship
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .meta import Base
|
||||
|
||||
|
||||
class Product(Base):
|
||||
__tablename__ = "products"
|
||||
__table_args__ = (UniqueConstraint("name", "units"),)
|
||||
class RateContract(Base):
|
||||
__tablename__ = "rate_contracts"
|
||||
|
||||
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
code = Column("code", Integer, unique=True)
|
||||
name = Column("name", Unicode(255), nullable=False)
|
||||
units = Column("units", Unicode(255), nullable=False)
|
||||
fraction = Column("fraction", Numeric(precision=15, scale=5), nullable=False)
|
||||
fraction_units = Column("fraction_units", Unicode(255), nullable=False)
|
||||
product_yield = Column("product_yield", Numeric(precision=15, scale=5), nullable=False)
|
||||
product_group_id = Column(
|
||||
"product_group_id",
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("product_groups.id"),
|
||||
nullable=False,
|
||||
)
|
||||
account_id = Column("account_id", UUID(as_uuid=True), ForeignKey("accounts.id"), nullable=False)
|
||||
price = Column("cost_price", Numeric(precision=15, scale=2), nullable=False)
|
||||
sale_price = Column("sale_price", Numeric(precision=15, scale=2), nullable=False)
|
||||
is_active = Column("is_active", Boolean, nullable=False)
|
||||
is_fixture = Column("is_fixture", Boolean, nullable=False)
|
||||
is_purchased = Column("is_purchased", Boolean, nullable=False)
|
||||
is_sold = Column("is_sold", Boolean, nullable=False)
|
||||
date = Column("date", Date, nullable=False, index=True)
|
||||
vendor_id = Column("vendor_id", UUID(as_uuid=True), ForeignKey("accounts.id"), nullable=False)
|
||||
valid_from = Column("valid_from", Date(), nullable=True)
|
||||
valid_till = Column("valid_till", Date(), nullable=True)
|
||||
narration = Column("narration", Unicode(1000), nullable=False)
|
||||
|
||||
product_group = relationship("ProductGroup", back_populates="products")
|
||||
batches = relationship("Batch", back_populates="product")
|
||||
inventories = relationship("Inventory", back_populates="product")
|
||||
recipes = relationship("Recipe", back_populates="product")
|
||||
account = relationship("Account", primaryjoin="Account.id==Product.account_id", back_populates="products")
|
||||
user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("users.id"), nullable=False)
|
||||
creation_date = Column("creation_date", DateTime(), nullable=False)
|
||||
last_edit_date = Column("last_edit_date", DateTime(), nullable=False)
|
||||
|
||||
user = relationship("User")
|
||||
vendor = relationship("AccountBase", back_populates="rate_contracts")
|
||||
items = relationship("RateContractItem", back_populates="rate_contract")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
code=None,
|
||||
name=None,
|
||||
units=None,
|
||||
fraction=None,
|
||||
fraction_units=None,
|
||||
product_yield=None,
|
||||
product_group_id=None,
|
||||
account_id=None,
|
||||
price=None,
|
||||
sale_price=None,
|
||||
is_active=None,
|
||||
is_purchased=None,
|
||||
is_sold=None,
|
||||
date=None,
|
||||
vendor_id=None,
|
||||
valid_from=None,
|
||||
valid_till=None,
|
||||
narration="",
|
||||
user_id=None,
|
||||
creation_date=None,
|
||||
last_edit_date=None,
|
||||
id_=None,
|
||||
is_fixture=False,
|
||||
):
|
||||
self.code = code
|
||||
self.name = name
|
||||
self.units = units
|
||||
self.fraction = fraction
|
||||
self.fraction_units = fraction_units
|
||||
self.product_yield = product_yield
|
||||
self.product_group_id = product_group_id
|
||||
self.account_id = account_id
|
||||
self.price = price
|
||||
self.sale_price = sale_price
|
||||
self.is_active = is_active
|
||||
self.is_purchased = is_purchased
|
||||
self.is_sold = is_sold
|
||||
self.date = date
|
||||
self.vendor_id = vendor_id
|
||||
self.valid_from = valid_from
|
||||
self.valid_till = valid_till
|
||||
self.narration = narration
|
||||
self.user_id = user_id
|
||||
self.creation_date = creation_date or datetime.utcnow()
|
||||
self.last_edit_date = last_edit_date or datetime.utcnow()
|
||||
self.id = id_
|
||||
self.is_fixture = is_fixture
|
||||
|
||||
@hybrid_property
|
||||
def full_name(self):
|
||||
return f"{self.name} ({self.units})" if self.units else self.name
|
||||
|
||||
@full_name.expression
|
||||
def full_name(cls):
|
||||
return cls.name + case([(cls.units != "", " (" + cls.units + ")")], else_="")
|
||||
|
||||
def create(self, db: Session):
|
||||
self.code = db.execute(select(func.coalesce(func.max(Product.code), 0) + 1)).scalar_one()
|
||||
db.add(self)
|
||||
return self
|
||||
|
||||
def can_delete(self, advanced_delete: bool):
|
||||
if self.is_fixture:
|
||||
return False, f"{self.name} is a fixture and cannot be edited or deleted."
|
||||
if self.is_active:
|
||||
return False, "Product is active"
|
||||
if len(self.inventories) > 0 and not advanced_delete:
|
||||
return False, "Product has entries"
|
||||
return True, ""
|
||||
|
||||
@classmethod
|
||||
def query(cls, q, is_purchased: bool = None, active: bool = None, db: Session = None):
|
||||
query_ = select(cls)
|
||||
if active is not None:
|
||||
query_ = query_.filter(cls.is_active == active)
|
||||
if is_purchased is not None:
|
||||
query_ = query_.filter(cls.is_purchased == is_purchased)
|
||||
if q is not None:
|
||||
for item in q.split():
|
||||
if item.strip() != "":
|
||||
query_ = query_.filter(cls.name.ilike(f"%{item}%"))
|
||||
return db.execute(query_).scalars().all()
|
||||
|
||||
@classmethod
|
||||
def suspense(cls):
|
||||
return uuid.UUID("aa79a643-9ddc-4790-ac7f-a41f9efb4c15")
|
||||
|
||||
@ -1,119 +1,38 @@
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
Column,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
Numeric,
|
||||
Unicode,
|
||||
UniqueConstraint,
|
||||
case,
|
||||
func,
|
||||
select, DateTime, Date,
|
||||
)
|
||||
from sqlalchemy import Column, ForeignKey, Numeric, UniqueConstraint
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
from sqlalchemy.orm import Session, relationship
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .meta import Base
|
||||
|
||||
|
||||
class RateContract(Base):
|
||||
__tablename__ = "rate_contracts"
|
||||
__table_args__ = (UniqueConstraint("name", "units"),)
|
||||
class RateContractItem(Base):
|
||||
__tablename__ = "rate_contract_items"
|
||||
__table_args__ = (UniqueConstraint("rate_contract_id", "product_id"),)
|
||||
|
||||
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
rate_contract_id = Column(
|
||||
"rate_contract_id",
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("rate_contracts.id"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False)
|
||||
price = Column("cost_price", Numeric(precision=15, scale=2), nullable=False)
|
||||
|
||||
user = relationship("User", primaryjoin="User.id==Voucher.user_id", cascade=None)
|
||||
creation_date = Column("creation_date", DateTime(), nullable=False)
|
||||
last_edit_date = Column("last_edit_date", DateTime(), nullable=False)
|
||||
|
||||
vendor_id = Column("vendor_id", UUID(as_uuid=True), ForeignKey("accounts.id"), nullable=False)
|
||||
|
||||
# product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False)
|
||||
# price = Column("cost_price", Numeric(precision=15, scale=2), nullable=False)
|
||||
|
||||
valid_from = Column("valid_from", Date(), nullable=True)
|
||||
valid_till = Column("valid_till", Date(), nullable=True)
|
||||
|
||||
user = relationship("User")
|
||||
vendor = relationship("Account", back_populates="rate_contracts")
|
||||
|
||||
# batches = relationship("Batch", back_populates="product")
|
||||
# inventories = relationship("Inventory", back_populates="product")
|
||||
# recipes = relationship("Recipe", back_populates="product")
|
||||
# account = relationship("Account", primaryjoin="Account.id==Product.account_id", back_populates="products")
|
||||
rate_contract = relationship("RateContract", back_populates="items")
|
||||
product = relationship("Product")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
code=None,
|
||||
name=None,
|
||||
units=None,
|
||||
fraction=None,
|
||||
fraction_units=None,
|
||||
product_yield=None,
|
||||
product_group_id=None,
|
||||
account_id=None,
|
||||
rate_contract_id=None,
|
||||
product_id=None,
|
||||
price=None,
|
||||
sale_price=None,
|
||||
is_active=None,
|
||||
is_purchased=None,
|
||||
is_sold=None,
|
||||
id_=None,
|
||||
is_fixture=False,
|
||||
):
|
||||
self.code = code
|
||||
self.name = name
|
||||
self.units = units
|
||||
self.fraction = fraction
|
||||
self.fraction_units = fraction_units
|
||||
self.product_yield = product_yield
|
||||
self.product_group_id = product_group_id
|
||||
self.account_id = account_id
|
||||
self.rate_contract_id = rate_contract_id
|
||||
self.product_id = product_id
|
||||
self.price = price
|
||||
self.sale_price = sale_price
|
||||
self.is_active = is_active
|
||||
self.is_purchased = is_purchased
|
||||
self.is_sold = is_sold
|
||||
self.id = id_
|
||||
self.is_fixture = is_fixture
|
||||
|
||||
@hybrid_property
|
||||
def full_name(self):
|
||||
return f"{self.name} ({self.units})" if self.units else self.name
|
||||
|
||||
@full_name.expression
|
||||
def full_name(cls):
|
||||
return cls.name + case([(cls.units != "", " (" + cls.units + ")")], else_="")
|
||||
|
||||
def create(self, db: Session):
|
||||
self.code = db.execute(select(func.coalesce(func.max(Product.code), 0) + 1)).scalar_one()
|
||||
db.add(self)
|
||||
return self
|
||||
|
||||
def can_delete(self, advanced_delete: bool):
|
||||
if self.is_fixture:
|
||||
return False, f"{self.name} is a fixture and cannot be edited or deleted."
|
||||
if self.is_active:
|
||||
return False, "Product is active"
|
||||
if len(self.inventories) > 0 and not advanced_delete:
|
||||
return False, "Product has entries"
|
||||
return True, ""
|
||||
|
||||
@classmethod
|
||||
def query(cls, q, is_purchased: bool = None, active: bool = None, db: Session = None):
|
||||
query_ = select(cls)
|
||||
if active is not None:
|
||||
query_ = query_.filter(cls.is_active == active)
|
||||
if is_purchased is not None:
|
||||
query_ = query_.filter(cls.is_purchased == is_purchased)
|
||||
if q is not None:
|
||||
for item in q.split():
|
||||
if item.strip() != "":
|
||||
query_ = query_.filter(cls.name.ilike(f"%{item}%"))
|
||||
return db.execute(query_).scalars().all()
|
||||
|
||||
@classmethod
|
||||
def suspense(cls):
|
||||
return uuid.UUID("aa79a643-9ddc-4790-ac7f-a41f9efb4c15")
|
||||
|
||||
187
brewman/brewman/routers/rate_contract.py
Normal file
187
brewman/brewman/routers/rate_contract.py
Normal file
@ -0,0 +1,187 @@
|
||||
import uuid
|
||||
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Request, Security, status
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
from ..core.session import (
|
||||
get_date,
|
||||
get_finish_date,
|
||||
get_start_date,
|
||||
set_date,
|
||||
set_period,
|
||||
)
|
||||
from ..db.session import SessionFuture
|
||||
from ..models.rate_contract import RateContract
|
||||
from ..models.rate_contract_item import RateContractItem
|
||||
from ..schemas.product import ProductLink
|
||||
from ..schemas.rate_contract import AccountLink
|
||||
from ..schemas.rate_contract import RateContract as RateContractSchema
|
||||
from ..schemas.rate_contract import RateContractIn as RateContractInSchema
|
||||
from ..schemas.rate_contract import RateContractItem as RateContractItemSchema
|
||||
from ..schemas.user import UserToken
|
||||
from ..schemas.user_link import UserLink
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("", response_model=RateContractSchema)
|
||||
async def save(
|
||||
data: RateContractInSchema,
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["rate-contracts"]),
|
||||
) -> RateContractSchema:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item = RateContract(
|
||||
date=data.date_,
|
||||
vendor_id=data.vendor.id_,
|
||||
valid_from=data.valid_from,
|
||||
valid_till=data.valid_till,
|
||||
narration=data.narration,
|
||||
user_id=user.id_,
|
||||
)
|
||||
db.add(item)
|
||||
add_items(item, data.items, db)
|
||||
set_date(data.date_.strftime("%d-%b-%Y"), request.session)
|
||||
set_period(data.valid_from.strftime("%d-%b-%Y"), data.valid_till.strftime("%d-%b-%Y"), request.session)
|
||||
db.commit()
|
||||
return rate_contract_info(item)
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
|
||||
|
||||
def add_items(rate_contract: RateContract, items: List[RateContractItemSchema], db: Session) -> None:
|
||||
for item in items:
|
||||
rci = RateContractItem(rate_contract_id=rate_contract.id, product_id=item.product.id_, price=item.price)
|
||||
rate_contract.items.append(rci)
|
||||
db.add(rci)
|
||||
|
||||
|
||||
@router.put("/{id_}", response_model=RateContractSchema)
|
||||
async def update_route(
|
||||
id_: uuid.UUID,
|
||||
data: RateContractInSchema,
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["rate-contracts"]),
|
||||
) -> RateContractSchema:
|
||||
try:
|
||||
with SessionFuture() as db:
|
||||
item: RateContract = db.execute(select(RateContract).where(RateContract.id == id_)).scalar_one()
|
||||
item.date = data.date_
|
||||
item.vendor_id = data.vendor.id_
|
||||
item.valid_from = data.valid_from
|
||||
item.valid_till = data.valid_till
|
||||
item.narration = data.narration
|
||||
item.user_id = user.id_
|
||||
update_items(item, data.items, db)
|
||||
set_date(data.date_.strftime("%d-%b-%Y"), request.session)
|
||||
set_period(data.valid_from.strftime("%d-%b-%Y"), data.valid_till.strftime("%d-%b-%Y"), request.session)
|
||||
db.commit()
|
||||
return rate_contract_info(item)
|
||||
except SQLAlchemyError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
|
||||
|
||||
def update_items(rate_contract: RateContract, items: List[RateContractItemSchema], db: Session):
|
||||
for it in range(len(rate_contract.items), 0, -1):
|
||||
item = rate_contract.items[it - 1]
|
||||
for j in range(len(items), 0, -1):
|
||||
new_item = items[j - 1]
|
||||
if new_item.id_ == item.id:
|
||||
item.product_id = new_item.product.id_
|
||||
item.price = new_item.price
|
||||
items.remove(new_item)
|
||||
break
|
||||
else:
|
||||
db.delete(item)
|
||||
rate_contract.items.remove(item)
|
||||
for item in items:
|
||||
rci = RateContractItem(rate_contract_id=rate_contract.id, product_id=item.product.id_, price=item.price)
|
||||
rate_contract.items.append(rci)
|
||||
db.add(rci)
|
||||
|
||||
|
||||
@router.delete("/{id_}", response_model=RateContractInSchema)
|
||||
async def delete_route(
|
||||
id_: uuid.UUID,
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["rate-contracts"]),
|
||||
) -> RateContractInSchema:
|
||||
with SessionFuture() as db:
|
||||
db.execute(delete(RateContractItem).where(RateContractItem.rate_contract_id == id_))
|
||||
db.execute(delete(RateContract).where(RateContract.id == id_))
|
||||
db.commit()
|
||||
return rate_contract_blank(request.session)
|
||||
|
||||
|
||||
@router.get("", response_model=RateContractInSchema)
|
||||
async def show_blank(
|
||||
request: Request,
|
||||
user: UserToken = Security(get_user, scopes=["rate-contracts"]),
|
||||
) -> RateContractInSchema:
|
||||
return rate_contract_blank(request.session)
|
||||
|
||||
|
||||
@router.get("/list", response_model=List[RateContractSchema])
|
||||
async def show_list(
|
||||
user: UserToken = Security(get_user),
|
||||
) -> List[RateContractSchema]:
|
||||
with SessionFuture() as db:
|
||||
return [
|
||||
rate_contract_info(item)
|
||||
for item in db.execute(select(RateContract).order_by(RateContract.date)).scalars().all()
|
||||
]
|
||||
|
||||
|
||||
@router.get("/{id_}", response_model=RateContractSchema)
|
||||
async def show_id(
|
||||
id_: uuid.UUID,
|
||||
user: UserToken = Security(get_user, scopes=["rate-contracts"]),
|
||||
) -> RateContractSchema:
|
||||
with SessionFuture() as db:
|
||||
item: RateContract = db.execute(select(RateContract).where(RateContract.id == id_)).scalar_one()
|
||||
return rate_contract_info(item)
|
||||
|
||||
|
||||
def rate_contract_info(item: RateContract) -> RateContractSchema:
|
||||
return RateContractSchema(
|
||||
id=item.id,
|
||||
date=item.date,
|
||||
vendor=AccountLink(id=item.vendor_id, name=item.vendor.name),
|
||||
validFrom=item.valid_from,
|
||||
validTill=item.valid_till,
|
||||
narration=item.narration,
|
||||
creationDate=item.creation_date,
|
||||
lastEditDate=item.last_edit_date,
|
||||
user=UserLink(id=item.user_id, name=item.user.name),
|
||||
items=[
|
||||
RateContractItemSchema(
|
||||
id=i.id,
|
||||
product=ProductLink(id=i.product_id, name=i.product.full_name),
|
||||
price=i.price,
|
||||
)
|
||||
for i in item.items
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def rate_contract_blank(session: dict) -> RateContractInSchema:
|
||||
return RateContractInSchema(
|
||||
date=get_date(session),
|
||||
validFrom=get_start_date(session),
|
||||
validTill=get_finish_date(session),
|
||||
narration="",
|
||||
items=[],
|
||||
)
|
||||
@ -1,8 +1,7 @@
|
||||
import uuid
|
||||
|
||||
from datetime import date, datetime
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import List, Optional
|
||||
|
||||
import brewman.schemas.voucher as output
|
||||
|
||||
@ -16,7 +15,6 @@ from ..core.session import get_first_day
|
||||
from ..db.session import SessionFuture
|
||||
from ..models.account import Account
|
||||
from ..models.account_base import AccountBase
|
||||
from ..models.account_type import AccountType
|
||||
from ..models.attendance import Attendance
|
||||
from ..models.attendance_type import AttendanceType
|
||||
from ..models.cost_centre import CostCentre
|
||||
|
||||
91
brewman/brewman/schemas/rate_contract.py
Normal file
91
brewman/brewman/schemas/rate_contract.py
Normal file
@ -0,0 +1,91 @@
|
||||
import uuid
|
||||
|
||||
from datetime import date, datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, validator
|
||||
|
||||
from . import to_camel
|
||||
from .account import AccountLink
|
||||
from .rate_contract_item import RateContractItem
|
||||
from .user_link import UserLink
|
||||
|
||||
|
||||
class RateContractIn(BaseModel):
|
||||
date_: date
|
||||
vendor: Optional[AccountLink]
|
||||
valid_from: date
|
||||
valid_till: date
|
||||
narration: str
|
||||
items: List[RateContractItem]
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
json_encoders = {
|
||||
date: lambda v: v.strftime("%d-%b-%Y"),
|
||||
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
|
||||
}
|
||||
|
||||
@validator("date_", pre=True)
|
||||
def parse_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
|
||||
@validator("valid_from", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y")
|
||||
|
||||
@validator("valid_till", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
if isinstance(value, date):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y")
|
||||
|
||||
|
||||
class RateContract(RateContractIn):
|
||||
id_: uuid.UUID
|
||||
creation_date: Optional[datetime]
|
||||
last_edit_date: Optional[datetime]
|
||||
user: Optional[UserLink]
|
||||
|
||||
class Config:
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
json_encoders = {
|
||||
date: lambda v: v.strftime("%d-%b-%Y"),
|
||||
datetime: lambda v: v.strftime("%d-%b-%Y %H:%I"),
|
||||
}
|
||||
|
||||
# @validator("date_", pre=True)
|
||||
# def parse_date(cls, value):
|
||||
# if isinstance(value, date):
|
||||
# return value
|
||||
# return datetime.strptime(value, "%d-%b-%Y").date()
|
||||
#
|
||||
# @validator("valid_from", pre=True)
|
||||
# def parse_creation_date(cls, value):
|
||||
# if isinstance(value, datetime):
|
||||
# return value
|
||||
# return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
#
|
||||
# @validator("valid_till", pre=True)
|
||||
# def parse_last_edit_date(cls, value):
|
||||
# if isinstance(value, datetime):
|
||||
# return value
|
||||
# return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("creation_date", pre=True)
|
||||
def parse_creation_date(cls, value):
|
||||
if isinstance(value, datetime):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
|
||||
@validator("last_edit_date", pre=True)
|
||||
def parse_last_edit_date(cls, value):
|
||||
if isinstance(value, datetime):
|
||||
return value
|
||||
return datetime.strptime(value, "%d-%b-%Y %H:%M")
|
||||
17
brewman/brewman/schemas/rate_contract_item.py
Normal file
17
brewman/brewman/schemas/rate_contract_item.py
Normal file
@ -0,0 +1,17 @@
|
||||
import uuid
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
|
||||
from brewman.schemas import to_camel
|
||||
from brewman.schemas.product import ProductLink
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class RateContractItem(BaseModel):
|
||||
id_: Optional[uuid.UUID]
|
||||
product: ProductLink
|
||||
price: Decimal = Field(ge=0, multiple_of=0.01)
|
||||
|
||||
class Config:
|
||||
alias_generator = to_camel
|
||||
Reference in New Issue
Block a user