Done: Product Group
Done: Product
This commit is contained in:
parent
aae48faf91
commit
9383cf84d4
brewman
@ -111,6 +111,18 @@ class Product(Base):
|
||||
return False, "Product has entries"
|
||||
return True, ""
|
||||
|
||||
@classmethod
|
||||
def query(cls, term, is_purchased=None, active=None, db=None):
|
||||
query_ = db.query(Product)
|
||||
if active is not None:
|
||||
query_ = query_.filter(Product.is_active == active)
|
||||
if is_purchased is not None:
|
||||
query_ = query_.filter(Product.is_purchased == is_purchased)
|
||||
if term is not None:
|
||||
for item in term.split():
|
||||
if item.strip() != "":
|
||||
query_ = query_.filter(Product.name.ilike("%" + item + "%"))
|
||||
|
||||
@classmethod
|
||||
def suspense(cls):
|
||||
return uuid.UUID("aa79a643-9ddc-4790-ac7f-a41f9efb4c15")
|
||||
@ -303,20 +315,20 @@ class AccountBase(Base):
|
||||
self.is_fixture = is_fixture
|
||||
|
||||
@classmethod
|
||||
def list(cls, type, name, reconcilable=None, active=None, dbsession=None):
|
||||
query = dbsession.query(cls)
|
||||
if type is not None:
|
||||
if not isinstance(type, int):
|
||||
type = int(type)
|
||||
query = query.filter(cls.type == type)
|
||||
def query(cls, q, type_, reconcilable=None, active=None, db=None):
|
||||
query_ = db.query(cls)
|
||||
if type_ is not None:
|
||||
if not isinstance(type_, int):
|
||||
type_ = int(type_)
|
||||
query_ = query_.filter(cls.type == type_)
|
||||
if reconcilable is not None:
|
||||
query = query.filter(cls.is_reconcilable == reconcilable)
|
||||
query_ = query_.filter(cls.is_reconcilable == reconcilable)
|
||||
if active is not None:
|
||||
query = query.filter(cls.is_active == active)
|
||||
if name is not None:
|
||||
for item in name.split():
|
||||
query = query.filter(cls.name.ilike("%" + item + "%"))
|
||||
return query.order_by(cls.name)
|
||||
query_ = query_.filter(cls.is_active == active)
|
||||
if q is not None:
|
||||
for item in q.split():
|
||||
query_ = query_.filter(cls.name.ilike("%" + item + "%"))
|
||||
return query_.order_by(cls.name)
|
||||
|
||||
def create(self, dbsession):
|
||||
code = (
|
||||
|
@ -151,7 +151,7 @@ async def show_term(
|
||||
count = c
|
||||
|
||||
list_ = []
|
||||
for index, item in enumerate(AccountBase.list(t, q, r, a, db)):
|
||||
for index, item in enumerate(AccountBase.query(q, t, r, a, db)):
|
||||
list_.append({"id": item.id, "name": item.name})
|
||||
if count is not None and index == count - 1:
|
||||
break
|
||||
@ -195,7 +195,7 @@ def balance(id_: uuid.UUID, date, db: Session):
|
||||
return 0 if bal is None else bal
|
||||
|
||||
|
||||
def account_info(id_, db):
|
||||
def account_info(id_: uuid.UUID, db: Session):
|
||||
if id_ is None:
|
||||
account = {
|
||||
"code": "(Auto)",
|
||||
@ -224,7 +224,7 @@ def account_info(id_, db):
|
||||
return account
|
||||
|
||||
|
||||
def delete_with_data(account, db):
|
||||
def delete_with_data(account: Account, db: Session):
|
||||
suspense_account = (
|
||||
db.query(Account).filter(Account.id == Account.suspense()).first()
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import traceback
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
@ -28,10 +29,16 @@ def save(
|
||||
user: User = Security(get_user, scopes=["cost-centres"]),
|
||||
):
|
||||
try:
|
||||
item = CostCentre(data.name)
|
||||
item = CostCentre(name=data.name)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
return cost_centre_info(item, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
|
@ -1,245 +1,203 @@
|
||||
import traceback
|
||||
import uuid
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
from sqlalchemy import desc
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import joinedload_all, Session
|
||||
|
||||
from brewman.models.master import Product, Account
|
||||
from brewman.models.validation_exception import ValidationError
|
||||
from brewman.models.voucher import Voucher, Batch, Inventory, VoucherType
|
||||
|
||||
from fastapi import APIRouter
|
||||
import brewman.schemas.master as schemas
|
||||
from ..core.security import User, get_current_active_user as get_user
|
||||
from ..db.session import SessionLocal
|
||||
from ..models.master import Product, Account
|
||||
from ..models.voucher import Voucher, Batch, Inventory, VoucherType
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/new") # "Products"
|
||||
def save(request):
|
||||
json = request.json_body
|
||||
|
||||
name = json.get("name", "").strip()
|
||||
if name == "":
|
||||
raise ValidationError("Name cannot be blank")
|
||||
|
||||
units = json.get("units", "").strip()
|
||||
|
||||
# Dependency
|
||||
def get_db():
|
||||
try:
|
||||
fraction = Decimal(json.get("fraction", 0))
|
||||
if fraction <= 0:
|
||||
raise ValidationError("Fraction must be a decimal > 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Fraction must be a decimal > 0")
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
fraction_units = json.get("fractionUnits", "").strip()
|
||||
|
||||
@router.post("/", response_model=schemas.Product)
|
||||
def save(
|
||||
data: schemas.ProductIn,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["products"]),
|
||||
):
|
||||
try:
|
||||
product_yield = Decimal(json.get("productYield", 1))
|
||||
if product_yield <= 0 or product_yield > 1:
|
||||
raise ValidationError("Yield must be a decimal > 0 <= 1")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Yield must be a decimal > 0 <= 1")
|
||||
|
||||
product_group = json.get("productGroup", None)
|
||||
if product_group is None:
|
||||
raise ValidationError("please choose a product group")
|
||||
product_group_id = uuid.UUID(product_group["id"])
|
||||
try:
|
||||
price = Decimal(json.get("price", 0))
|
||||
if price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
try:
|
||||
sale_price = Decimal(json.get("salePrice", 0))
|
||||
if price < 0:
|
||||
raise ValidationError("Sale Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
is_active = json.get("isActive", True)
|
||||
is_purchased = json.get("isPurchased", True)
|
||||
is_sold = json.get("isSold", True)
|
||||
item = Product(
|
||||
0,
|
||||
name,
|
||||
units,
|
||||
fraction,
|
||||
fraction_units,
|
||||
product_yield,
|
||||
product_group_id,
|
||||
Account.all_purchases(),
|
||||
price,
|
||||
sale_price,
|
||||
is_active,
|
||||
is_purchased,
|
||||
is_sold,
|
||||
).create(request.dbsession)
|
||||
transaction.commit()
|
||||
return product_info(item.id, request.dbsession)
|
||||
|
||||
|
||||
@router.put("/{id}") # "Products"
|
||||
def update(request):
|
||||
item = (
|
||||
request.dbsession.query(Product)
|
||||
.filter(Product.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
if item.is_fixture:
|
||||
raise ValidationError(
|
||||
"{0} is a fixture and cannot be edited or deleted.".format(item.full_name)
|
||||
item = Product(
|
||||
name=data.name,
|
||||
units=data.units,
|
||||
fraction=data.fraction,
|
||||
fraction_units=data.fraction_units,
|
||||
product_yield=data.product_yield,
|
||||
product_group_id=data.product_group.id_,
|
||||
account_id=Account.all_purchases(),
|
||||
price=data.price,
|
||||
sale_price=data.sale_price,
|
||||
is_active=data.is_active,
|
||||
is_purchased=data.is_purchased,
|
||||
is_sold=data.is_sold
|
||||
).create(db)
|
||||
db.commit()
|
||||
return product_info(item.id, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
item.name = request.json_body["name"].strip()
|
||||
item.units = request.json_body["units"].strip()
|
||||
try:
|
||||
item.fraction = Decimal(request.json_body["fraction"])
|
||||
if item.fraction <= 0:
|
||||
raise ValidationError("Fraction must be a decimal > 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Fraction must be a decimal > 0")
|
||||
item.fraction_units = request.json_body["fractionUnits"]
|
||||
|
||||
try:
|
||||
item.product_yield = Decimal(request.json_body["productYield"])
|
||||
if item.product_yield <= 0 or item.product_yield > 1:
|
||||
raise ValidationError("Yield must be a decimal > 0 <= 1")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Yield must be a decimal > 0 <= 1")
|
||||
|
||||
item.product_group_id = uuid.UUID(request.json_body["productGroup"]["id"])
|
||||
item.account_id = Account.all_purchases()
|
||||
try:
|
||||
item.price = Decimal(request.json_body["price"])
|
||||
if item.price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
try:
|
||||
item.sale_price = Decimal(request.json_body["salePrice"])
|
||||
if item.sale_price < 0:
|
||||
raise ValidationError("Sale Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Sale Price must be a decimal >= 0")
|
||||
item.is_active = request.json_body["isActive"]
|
||||
item.is_fixture = request.json_body["isFixture"]
|
||||
item.is_purchased = request.json_body["isPurchased"]
|
||||
item.is_sold = request.json_body["isSold"]
|
||||
transaction.commit()
|
||||
return product_info(item.id, request.dbsession)
|
||||
|
||||
|
||||
@router.delete("/{id}") # "Products"
|
||||
def delete(request):
|
||||
product = (
|
||||
request.dbsession.query(Product)
|
||||
.filter(Product.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
can_delete, reason = product.can_delete(request.has_permission("Advanced Delete"))
|
||||
@router.put("/{id_}", response_model=schemas.Product)
|
||||
def update(
|
||||
id_: uuid.UUID,
|
||||
data: schemas.ProductIn,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["products"]),
|
||||
):
|
||||
try:
|
||||
item: Product = db.query(Product).filter(Product.id == id_).first()
|
||||
if item.is_fixture:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"{item.name} is a fixture and cannot be edited or deleted.",
|
||||
)
|
||||
item.name = data.name
|
||||
item.units = data.units
|
||||
item.fraction = data.fraction
|
||||
item.fraction_units = data.fraction_units
|
||||
item.product_yield = data.product_yield
|
||||
item.product_group_id = data.product_group.id_
|
||||
item.account_id = Account.all_purchases()
|
||||
item.price = data.price
|
||||
item.sale_price = data.sale_price
|
||||
item.is_active = data.is_active
|
||||
item.is_purchased = data.is_purchased
|
||||
item.is_sold = data.is_sold
|
||||
db.commit()
|
||||
return product_info(item.id, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{id_}")
|
||||
def delete(
|
||||
id_: uuid.UUID,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["products"]),
|
||||
):
|
||||
product: Product = db.query(Product).filter(Product.id == id_).first()
|
||||
can_delete, reason = product.can_delete("Advanced Delete" in user.permissions)
|
||||
|
||||
if can_delete:
|
||||
delete_with_data(product, request)
|
||||
transaction.commit()
|
||||
return product_info(None, request.dbsession)
|
||||
delete_with_data(product, db)
|
||||
db.commit()
|
||||
return product_info(None, db)
|
||||
else:
|
||||
transaction.abort()
|
||||
response = Response("Cannot delete product because {0}".format(reason))
|
||||
response.status_int = 500
|
||||
return response
|
||||
db.abort()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Cannot delete account because {reason}",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{id}") # "Products"
|
||||
def show_id(request):
|
||||
return product_info(uuid.UUID(request.matchdict.get("id", None)), request.dbsession)
|
||||
@router.get("/") # "Products"
|
||||
def show_blank(
|
||||
db: Session = Depends(get_db), user: User = Security(get_user, scopes=["products"])
|
||||
):
|
||||
return product_info(None, db)
|
||||
|
||||
|
||||
@router.get("/new") # "Products"
|
||||
def show_blank(request):
|
||||
return product_info(None, request.dbsession)
|
||||
@router.get("/list")
|
||||
def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)):
|
||||
return [
|
||||
{
|
||||
"id": item.id,
|
||||
"code": item.code,
|
||||
"name": item.name,
|
||||
"units": item.units,
|
||||
"costPrice": item.price,
|
||||
"salePrice": item.sale_price,
|
||||
"productGroup": item.product_group.name,
|
||||
"isActive": item.is_active,
|
||||
"fraction": item.fraction,
|
||||
"fractionUnits": item.fraction_units,
|
||||
"isPurchased": item.is_purchased,
|
||||
"isSold": item.is_sold,
|
||||
"productYield": item.product_yield,
|
||||
"isFixture": item.is_fixture,
|
||||
}
|
||||
for item in db.query(Product).order_by(desc(Product.is_active)).order_by(Product.product_group_id).order_by(Product.name).all()
|
||||
]
|
||||
|
||||
|
||||
@router.get("/", ) # "Authenticated"
|
||||
def show_list(l: bool):
|
||||
list_ = (
|
||||
request.dbsession.query(Product)
|
||||
.order_by(desc(Product.is_active))
|
||||
.order_by(Product.product_group_id)
|
||||
.order_by(Product.name)
|
||||
.all()
|
||||
)
|
||||
products = []
|
||||
for item in list_:
|
||||
products.append(
|
||||
@router.get("/query")
|
||||
async def show_term(
|
||||
t: str = None,
|
||||
a: bool = None,
|
||||
c: int = None,
|
||||
p: bool = None,
|
||||
e: bool = False,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_user),
|
||||
):
|
||||
count = c
|
||||
extended = e
|
||||
list_ = []
|
||||
for index, item in enumerate(Product.query(t, p, a, db)):
|
||||
list_.append(
|
||||
{
|
||||
"id": item.id,
|
||||
"code": item.code,
|
||||
"name": item.name,
|
||||
"name": item.full_name,
|
||||
"price": item.price,
|
||||
"units": item.units,
|
||||
"costPrice": item.price,
|
||||
"salePrice": item.sale_price,
|
||||
"productGroup": item.product_group.name,
|
||||
"isActive": item.is_active,
|
||||
"fraction": item.fraction,
|
||||
"fractionUnits": item.fraction_units,
|
||||
"isPurchased": item.is_purchased,
|
||||
"isSold": item.is_sold,
|
||||
"productYield": item.product_yield,
|
||||
"isFixture": item.is_fixture,
|
||||
"isSold": item.is_sold,
|
||||
"salePrice": item.sale_price,
|
||||
} if extended else {
|
||||
"id": item.id, "name": item.full_name, "price": item.price
|
||||
}
|
||||
)
|
||||
return products
|
||||
if count is not None and index == count - 1:
|
||||
break
|
||||
return sorted(list_, key=lambda k: k["name"])
|
||||
|
||||
|
||||
@router.get("/") # "Authenticated"
|
||||
async def show_term(t: str):
|
||||
term = request.GET.get("t", None)
|
||||
term = term.strip() if term is not None and term.strip() != "" else None
|
||||
active = request.GET.get("a", None)
|
||||
active = active if active is not None else None
|
||||
count = request.GET.get("c", None)
|
||||
count = None if count is None or count == "" else int(count)
|
||||
is_purchased = request.GET.get("p", None)
|
||||
is_purchased = is_purchased if is_purchased is not None else None
|
||||
extended = request.GET.get("e", False)
|
||||
|
||||
def add_list(query):
|
||||
local_results = []
|
||||
for index, item in enumerate(query):
|
||||
if extended:
|
||||
product = {
|
||||
"id": item.id,
|
||||
"name": item.full_name,
|
||||
"price": item.price,
|
||||
"units": item.units,
|
||||
"fraction": item.fraction,
|
||||
"fractionUnits": item.fraction_units,
|
||||
"productYield": item.product_yield,
|
||||
"isSold": item.is_sold,
|
||||
"salePrice": item.sale_price,
|
||||
}
|
||||
else:
|
||||
product = {"id": item.id, "name": item.full_name, "price": item.price}
|
||||
local_results.append(product)
|
||||
if count is not None and index == count - 1:
|
||||
break
|
||||
return local_results
|
||||
|
||||
result_list = []
|
||||
|
||||
query = request.dbsession.query(Product)
|
||||
if active is not None:
|
||||
query = query.filter(Product.is_active == active)
|
||||
if is_purchased is not None:
|
||||
query = query.filter(Product.is_purchased == is_purchased)
|
||||
if term is not None:
|
||||
for item in term.split():
|
||||
if item.strip() != "":
|
||||
query = query.filter(Product.name.ilike("%" + item + "%"))
|
||||
result_list += add_list(query)
|
||||
|
||||
return sorted(result_list, key=lambda k: k["name"])
|
||||
@router.get("/{id_}")
|
||||
def show_id(
|
||||
id_: uuid.UUID,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["accounts"]),
|
||||
):
|
||||
return product_info(id_, db)
|
||||
|
||||
|
||||
def product_info(id_, dbsession):
|
||||
def product_info(id_: Optional[uuid.UUID], db: Session):
|
||||
if id_ is None:
|
||||
product = {
|
||||
"code": "(Auto)",
|
||||
@ -249,7 +207,7 @@ def product_info(id_, dbsession):
|
||||
"isSold": False,
|
||||
}
|
||||
else:
|
||||
product = dbsession.query(Product).filter(Product.id == id_).first()
|
||||
product = db.query(Product).filter(Product.id == id_).first()
|
||||
product = {
|
||||
"id": product.id,
|
||||
"code": product.code,
|
||||
@ -270,17 +228,17 @@ def product_info(id_, dbsession):
|
||||
return product
|
||||
|
||||
|
||||
def delete_with_data(product, request):
|
||||
def delete_with_data(product: Product, db: Session):
|
||||
suspense_product = (
|
||||
request.dbsession.query(Product)
|
||||
db.query(Product)
|
||||
.filter(Product.id == Product.suspense())
|
||||
.first()
|
||||
)
|
||||
suspense_batch = (
|
||||
request.dbsession.query(Batch).filter(Batch.id == Batch.suspense()).first()
|
||||
db.query(Batch).filter(Batch.id == Batch.suspense()).first()
|
||||
)
|
||||
query = (
|
||||
request.dbsession.query(Voucher)
|
||||
db.query(Voucher)
|
||||
.options(joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True))
|
||||
.filter(Voucher.inventories.any(Inventory.product_id == product.id))
|
||||
.all()
|
||||
@ -296,7 +254,7 @@ def delete_with_data(product, request):
|
||||
else:
|
||||
others = True
|
||||
if not others and voucher.type == VoucherType.by_id("Issue"):
|
||||
request.dbsession.delete(voucher)
|
||||
db.delete(voucher)
|
||||
else:
|
||||
if sus_inv is None:
|
||||
prod_inv.product = suspense_product
|
||||
@ -305,15 +263,11 @@ def delete_with_data(product, request):
|
||||
prod_inv.tax = 0
|
||||
prod_inv.discount = 0
|
||||
prod_inv.batch = suspense_batch
|
||||
voucher.narration += "\nSuspense \u20B9{0:,.2f} is {1}".format(
|
||||
prod_inv.amount, product.name
|
||||
)
|
||||
voucher.narration += f"\nSuspense \u20B9{prod_inv.amount:,.2f} is {product.name}"
|
||||
else:
|
||||
sus_inv.quantity += prod_inv.amount
|
||||
request.dbsession.delete(prod_inv)
|
||||
voucher.narration += "\nDeleted \u20B9{0:,.2f} of {1}".format(
|
||||
prod_inv.amount, product.name
|
||||
)
|
||||
db.delete(prod_inv)
|
||||
voucher.narration += f"\nDeleted \u20B9{prod_inv.amount:,.2f} of {product.name}"
|
||||
for batch in product.batches:
|
||||
request.dbsession.delete(batch)
|
||||
request.dbsession.delete(product)
|
||||
db.delete(batch)
|
||||
db.delete(product)
|
||||
|
@ -1,90 +1,150 @@
|
||||
import traceback
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import brewman.schemas.master as schemas
|
||||
from ..core.security import User, get_current_active_user as get_user
|
||||
from ..db.session import SessionLocal
|
||||
from brewman.models.master import ProductGroup
|
||||
from brewman.models.validation_exception import ValidationError
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/new") # "Product Groups"
|
||||
def save(request):
|
||||
item = ProductGroup(request.json_body["name"])
|
||||
request.dbsession.add(item)
|
||||
transaction.commit()
|
||||
return product_group_info(item.id, request.dbsession)
|
||||
# Dependency
|
||||
def get_db():
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@router.put("/{id}") # "Product Groups"
|
||||
def update(request):
|
||||
item = (
|
||||
request.dbsession.query(ProductGroup)
|
||||
.filter(ProductGroup.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
if item.is_fixture:
|
||||
raise ValidationError(
|
||||
"{0} is a fixture and cannot be edited or deleted.".format(item.name)
|
||||
@router.post("/", response_model=schemas.ProductGroup)
|
||||
def save(
|
||||
data: schemas.ProductGroupIn,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["product-groups"]),
|
||||
):
|
||||
try:
|
||||
item = ProductGroup(name=data.name)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
return product_group_info(item, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
item.name = request.json_body["name"]
|
||||
transaction.commit()
|
||||
return product_group_info(item.id, request.dbsession)
|
||||
|
||||
|
||||
@router.delete("/{id}") # "Product Groups"
|
||||
def delete(request):
|
||||
item = (
|
||||
request.dbsession.query(ProductGroup)
|
||||
.filter(ProductGroup.id == uuid.UUID(request.matchdict["id"]))
|
||||
.first()
|
||||
)
|
||||
@router.put("/{id_}", response_model=schemas.ProductGroup)
|
||||
def update(
|
||||
id_: uuid.UUID,
|
||||
data: schemas.ProductGroupIn,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["product-groups"]),
|
||||
):
|
||||
try:
|
||||
item = db.query(ProductGroup).filter(ProductGroup.id == id_).first()
|
||||
if item.is_fixture:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"{item.name} is a fixture and cannot be edited or deleted.",
|
||||
)
|
||||
item.name = data.name
|
||||
db.commit()
|
||||
return product_group_info(item, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{id_}")
|
||||
def delete(
|
||||
id_: uuid.UUID,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["product-groups"]),
|
||||
):
|
||||
try:
|
||||
item = db.query(ProductGroup).filter(ProductGroup.id == id_).first()
|
||||
|
||||
if item is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Product Group not found",
|
||||
)
|
||||
elif item.is_fixture:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"{item.name} is a fixture and cannot be edited or deleted.",
|
||||
)
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Product Group deletion not implemented",
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
|
||||
|
||||
@router.get("/")
|
||||
def show_blank(
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["product-groups"]),
|
||||
):
|
||||
return product_group_info(None, db)
|
||||
|
||||
|
||||
@router.get("/list", response_model=List[schemas.ProductGroup])
|
||||
async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)):
|
||||
return[
|
||||
{"id": item.id, "name": item.name, "isFixture": item.is_fixture}
|
||||
for item in db.query(ProductGroup).order_by(ProductGroup.name).all()
|
||||
]
|
||||
|
||||
|
||||
@router.get("/{id_}", response_model=schemas.ProductGroup)
|
||||
def show_id(
|
||||
id_: uuid.UUID,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Security(get_user, scopes=["product-groups"]),
|
||||
):
|
||||
item = db.query(ProductGroup).filter(ProductGroup.id == id_).first()
|
||||
return product_group_info(item, db)
|
||||
|
||||
|
||||
def product_group_info(item: Optional[ProductGroup], db):
|
||||
if item is None:
|
||||
response = Response("Product Group not Found")
|
||||
response.status_int = 500
|
||||
return response
|
||||
elif item.is_fixture:
|
||||
raise ValidationError(
|
||||
"{0} is a fixture and cannot be edited or deleted.".format(item.name)
|
||||
)
|
||||
else:
|
||||
response = Response("Product Group deletion not implemented")
|
||||
response.status_int = 500
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/{id}") # "Product Groups"
|
||||
def show_id(request):
|
||||
return product_group_info(
|
||||
uuid.UUID(request.matchdict.get("id", None)), request.dbsession
|
||||
)
|
||||
|
||||
|
||||
@router.get("/new") # "Product Groups"
|
||||
def show_blank(request):
|
||||
return product_group_info(None, request.dbsession)
|
||||
|
||||
|
||||
@router.get("/") # "Authenticated"
|
||||
async def show_list(l: bool):
|
||||
list_ = request.dbsession.query(ProductGroup).order_by(ProductGroup.name).all()
|
||||
product_groups = []
|
||||
for item in list_:
|
||||
product_groups.append(
|
||||
{"id": item.id, "name": item.name, "isFixture": item.is_fixture}
|
||||
)
|
||||
return product_groups
|
||||
|
||||
|
||||
def product_group_info(id_, dbsession):
|
||||
if id_ is None:
|
||||
return {"name": ''}
|
||||
else:
|
||||
product_group = (
|
||||
dbsession.query(ProductGroup).filter(ProductGroup.id == id_).first()
|
||||
)
|
||||
return {
|
||||
"id": product_group.id,
|
||||
"name": product_group.name,
|
||||
"isFixture": product_group.is_fixture,
|
||||
"name": "",
|
||||
"isFixture": False,
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"id": item.id,
|
||||
"name": item.name,
|
||||
"isFixture": item.is_fixture,
|
||||
}
|
||||
|
@ -11,23 +11,59 @@ def to_camel(string: str) -> str:
|
||||
return ''.join([first] + [word.capitalize() for word in others])
|
||||
|
||||
|
||||
class Product(BaseModel):
|
||||
class AccountLink(BaseModel):
|
||||
id_: uuid.UUID = Field(...)
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
|
||||
|
||||
class ProductGroupIn(BaseModel):
|
||||
name: str = Field(..., min_length=1)
|
||||
|
||||
|
||||
class ProductGroup(ProductGroupIn):
|
||||
id_: uuid.UUID
|
||||
code: int
|
||||
name: str
|
||||
units: str
|
||||
fraction: Decimal
|
||||
fraction_units: str
|
||||
product_yield: Decimal
|
||||
product_group_id: uuid.UUID
|
||||
account_id: uuid.UUID
|
||||
price: Decimal
|
||||
sale_price: Decimal
|
||||
is_active: bool
|
||||
is_fixture: bool
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
|
||||
|
||||
class ProductGroupLink(BaseModel):
|
||||
id_: uuid.UUID = Field(...)
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
|
||||
|
||||
class ProductIn(BaseModel):
|
||||
name: str = Field(..., min_length=1)
|
||||
units: str
|
||||
fraction: Decimal = Field(ge=0, multiple_of=0.00001, default=0)
|
||||
fraction_units: str
|
||||
product_yield: Decimal = Field(ge=0, le=1, multiple_of=0.00001, default=1)
|
||||
product_group: ProductGroupLink = Field(...)
|
||||
account_id: AccountLink = Field(...)
|
||||
price: Decimal = Field(ge=0, multiple_of=0.01, default=0)
|
||||
sale_price: Decimal = Field(ge=0, multiple_of=0.01, default=0)
|
||||
is_active: bool
|
||||
is_purchased: bool
|
||||
is_sold: bool
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
anystr_strip_whitespace = True
|
||||
alias_generator = to_camel
|
||||
|
||||
|
||||
class Product(ProductIn):
|
||||
id_: uuid.UUID
|
||||
code: int
|
||||
is_fixture: bool
|
||||
|
||||
|
||||
class Recipe(BaseModel):
|
||||
id_: uuid.UUID
|
||||
@ -53,14 +89,8 @@ class RecipeItem(BaseModel):
|
||||
price: int
|
||||
|
||||
|
||||
class ProductGroup(BaseModel):
|
||||
id_: uuid.UUID
|
||||
name: str
|
||||
is_fixture: bool
|
||||
|
||||
|
||||
class CostCentreLink(BaseModel):
|
||||
id_: uuid.UUID
|
||||
id_: uuid.UUID = Field(...)
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
|
Loading…
x
Reference in New Issue
Block a user