Fix: Purchase edit will make sure that there are no backdated issues.
Fix: Purchase edit will also update issue prices. Chore: Simplify loop-in-loops
This commit is contained in:
parent
6d0d95070b
commit
119c5b71f1
@ -30,13 +30,13 @@ def post_check_batch_integrity(
|
||||
) -> List[schemas.BatchIntegrity]:
|
||||
|
||||
with SessionFuture() as db:
|
||||
info = batches(db) + batch_dates(db)
|
||||
info = negative_batches(db) + batch_dates(db)
|
||||
fix_batch_prices(db)
|
||||
db.commit()
|
||||
return info
|
||||
|
||||
|
||||
def batches(db: Session) -> List[schemas.BatchIntegrity]:
|
||||
def negative_batches(db: Session) -> List[schemas.BatchIntegrity]:
|
||||
inv_sum = func.sum(Inventory.quantity * Journal.debit).label("quantity")
|
||||
list_ = db.execute(
|
||||
select(Batch, Product.full_name, inv_sum)
|
||||
@ -153,20 +153,36 @@ def batch_dates(db: Session) -> List[schemas.BatchIntegrity]:
|
||||
|
||||
|
||||
def fix_batch_prices(db: Session) -> None:
|
||||
quantities = (
|
||||
list_ = (
|
||||
db.execute(
|
||||
select(Batch)
|
||||
.join(Batch.product)
|
||||
.join(Batch.inventories)
|
||||
.join(Inventory.voucher)
|
||||
.where(Batch.rate != Inventory.rate)
|
||||
.options(contains_eager(Batch.product), contains_eager(Batch.inventories).contains_eager(Inventory.voucher))
|
||||
.options(contains_eager(Batch.inventories))
|
||||
)
|
||||
.unique()
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
|
||||
for batch in quantities:
|
||||
for batch in list_:
|
||||
for inv in batch.inventories:
|
||||
refresh_voucher(inv.voucher.id, batch.product_id, db)
|
||||
refresh_voucher(inv.voucher_id, inv.product_id, db)
|
||||
|
||||
|
||||
def fix_single_batch_prices(batch_id: uuid.UUID, db: Session) -> None:
|
||||
list_ = (
|
||||
db.execute(
|
||||
select(Batch)
|
||||
.join(Batch.inventories)
|
||||
.where(Batch.id == batch_id, Batch.rate != Inventory.rate)
|
||||
.options(contains_eager(Batch.inventories))
|
||||
)
|
||||
.unique()
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
|
||||
for batch in list_:
|
||||
for inv in batch.inventories:
|
||||
refresh_voucher(inv.voucher_id, inv.product_id, db)
|
||||
|
@ -215,15 +215,12 @@ def update_employee_benefits(
|
||||
exp, total = 0, 0
|
||||
for i in range(len(voucher.employee_benefits), 0, -1):
|
||||
item = voucher.employee_benefits[i - 1]
|
||||
found = False
|
||||
for j in range(len(employee_benefits), 0, -1):
|
||||
new_item = employee_benefits[j - 1]
|
||||
if new_item.id_ == item.id:
|
||||
exp += item.esi_er + item.pf_er
|
||||
total += item.esi_ee + item.pf_ee + item.esi_er + item.pf_er
|
||||
employee_benefits.remove(new_item)
|
||||
break
|
||||
if not found:
|
||||
index = next((idx for (idx, d) in enumerate(employee_benefits) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
employee_benefits.pop(index)
|
||||
exp += item.esi_er + item.pf_er
|
||||
total += item.esi_ee + item.pf_ee + item.esi_er + item.pf_er
|
||||
else:
|
||||
voucher.employee_benefits.remove(item)
|
||||
voucher.journals.remove(item.journal)
|
||||
new_exp, new_total = save_employee_benefits(voucher, employee_benefits, days_in_month, db)
|
||||
|
@ -28,7 +28,12 @@ from ..schemas.inventory import Inventory as InventorySchema
|
||||
from ..schemas.user import UserToken
|
||||
from . import get_lock_info
|
||||
from .db_image import save_files, update_files
|
||||
from .voucher import blank_voucher, check_voucher_edit_allowed, voucher_info
|
||||
from .voucher import (
|
||||
blank_voucher,
|
||||
check_voucher_edit_allowed,
|
||||
get_batch_quantity,
|
||||
voucher_info,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
@ -251,60 +256,57 @@ def update_inventories(
|
||||
batch_consumed: Optional[bool],
|
||||
db: Session,
|
||||
):
|
||||
old_set = set([(i.id, i.batch_id) for i in voucher.inventories])
|
||||
new_set = set([(i.id_, i.batch.id_) for i in inventories if i.id_ is not None])
|
||||
if len(new_set - old_set):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Product / Batch cannot be changed",
|
||||
)
|
||||
amount: Decimal = Decimal(0)
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
found = False
|
||||
for j in range(len(inventories), 0, -1):
|
||||
i = inventories[j - 1]
|
||||
if item.id == i.id_:
|
||||
batch = db.execute(select(Batch).where(Batch.id == i.batch.id_)).scalar_one()
|
||||
found = True
|
||||
if item.batch_id != batch.id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Product / Batch cannot be changed",
|
||||
)
|
||||
if batch_consumed and i.quantity - item.quantity > item.batch.quantity_remaining:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Maximum quantity available for {item.product.full_name} "
|
||||
f"is {item.quantity + item.batch.quantity_remaining}",
|
||||
)
|
||||
if item.batch.name > voucher.date:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Batch of {item.product.name} was purchased after the issue date",
|
||||
)
|
||||
batch = db.execute(select(Batch).where(Batch.id == item.batch_id)).scalar_one()
|
||||
batch_quantity = get_batch_quantity(item.batch_id, voucher.id, db)
|
||||
index = next((idx for (idx, d) in enumerate(inventories) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
new_inventory = inventories.pop(index)
|
||||
if batch_consumed and new_inventory.quantity > batch_quantity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Maximum quantity available for {item.product.full_name} is {batch_quantity}",
|
||||
)
|
||||
if item.batch.name > voucher.date:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Batch of {item.product.name} was purchased after the issue date",
|
||||
)
|
||||
|
||||
if batch_consumed is None:
|
||||
pass
|
||||
elif batch_consumed:
|
||||
item.batch.quantity_remaining -= i.quantity - item.quantity
|
||||
else:
|
||||
item.batch.quantity_remaining += i.quantity - item.quantity
|
||||
|
||||
item.quantity = i.quantity
|
||||
item.rate = batch.rate
|
||||
item.tax = batch.tax
|
||||
item.discount = batch.discount
|
||||
amount += round(item.amount, 2)
|
||||
|
||||
inventories.remove(i)
|
||||
break
|
||||
if not found:
|
||||
if batch_consumed is None:
|
||||
pass
|
||||
elif batch_consumed:
|
||||
item.batch.quantity_remaining += item.quantity
|
||||
item.batch.quantity_remaining = batch_quantity - new_inventory.quantity
|
||||
else:
|
||||
if item.batch.quantity_remaining < item.quantity:
|
||||
item.batch.quantity_remaining = batch_quantity + new_inventory.quantity
|
||||
|
||||
item.quantity = new_inventory.quantity
|
||||
item.rate = batch.rate
|
||||
item.tax = batch.tax
|
||||
item.discount = batch.discount
|
||||
amount += round(item.amount, 2)
|
||||
else:
|
||||
if batch_consumed is None:
|
||||
pass
|
||||
elif batch_consumed:
|
||||
item.batch.quantity_remaining = batch_quantity
|
||||
else:
|
||||
if batch_quantity < item.quantity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Product {item.product.name} cannot be removed,"
|
||||
f" minimum quantity is {item.batch.quantity_remaining}",
|
||||
f" minimum quantity is {batch_quantity}",
|
||||
)
|
||||
item.batch.quantity_remaining -= item.quantity
|
||||
item.batch.quantity_remaining = batch_quantity
|
||||
db.delete(item)
|
||||
voucher.inventories.remove(item)
|
||||
amount += save_inventories(voucher, inventories, batch_consumed, db)
|
||||
|
@ -146,19 +146,15 @@ def update_voucher(id_: uuid.UUID, data: schema_in.JournalIn, user: UserToken, d
|
||||
|
||||
for i in range(len(voucher.journals), 0, -1):
|
||||
item = voucher.journals[i - 1]
|
||||
found = False
|
||||
for j in range(len(data.journals), 0, -1):
|
||||
new_item = data.journals[j - 1]
|
||||
if new_item.id_ is not None and item.id == new_item.id_:
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == new_item.account.id_)).scalar_one()
|
||||
found = True
|
||||
item.debit = new_item.debit
|
||||
item.amount = round(new_item.amount, 2)
|
||||
item.account_id = account.id
|
||||
item.cost_centre_id = account.cost_centre_id
|
||||
data.journals.remove(new_item)
|
||||
break
|
||||
if not found:
|
||||
index = next((idx for (idx, d) in enumerate(data.journals) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
new_item = data.journals.pop(index)
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == new_item.account.id_)).scalar_one()
|
||||
item.debit = new_item.debit
|
||||
item.amount = round(new_item.amount, 2)
|
||||
item.account_id = account.id
|
||||
item.cost_centre_id = account.cost_centre_id
|
||||
else:
|
||||
voucher.journals.remove(item)
|
||||
for new_item in data.journals:
|
||||
account = db.execute(select(AccountBase).where(AccountBase.id == new_item.account.id_)).scalar_one()
|
||||
|
@ -28,8 +28,14 @@ from ..models.voucher_type import VoucherType
|
||||
from ..schemas.inventory import Inventory as InventorySchema
|
||||
from ..schemas.user import UserToken
|
||||
from . import get_lock_info
|
||||
from .batch_integrity import fix_single_batch_prices
|
||||
from .db_image import save_files, update_files
|
||||
from .voucher import blank_voucher, check_voucher_edit_allowed, voucher_info
|
||||
from .voucher import (
|
||||
blank_voucher,
|
||||
check_voucher_edit_allowed,
|
||||
get_batch_quantity,
|
||||
voucher_info,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
@ -224,11 +230,17 @@ def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, new_inventories: Li
|
||||
)
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
quantity_consumed = -1 * get_batch_quantity(item.batch_id, voucher.id, db)
|
||||
index = next((idx for (idx, d) in enumerate(new_inventories) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
new_inventory = new_inventories.pop(index)
|
||||
product = db.execute(select(Product).where(Product.id == new_inventory.product.id_)).scalar_one()
|
||||
rc_price = rate_contract_price(product.id, vendor_id, voucher.date, db)
|
||||
if batch_has_older_vouchers(item.batch_id, voucher.date, voucher.id, db):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"{item.product.name} has older vouchers",
|
||||
)
|
||||
if rc_price is not None and rc_price != new_inventory.rate:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
@ -237,20 +249,14 @@ def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, new_inventories: Li
|
||||
if rc_price is not None:
|
||||
new_inventory.tax = 0
|
||||
new_inventory.discount = 0
|
||||
old_quantity = round(Decimal(item.quantity), 2)
|
||||
quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2)
|
||||
if new_inventory.quantity < (old_quantity - quantity_remaining):
|
||||
if new_inventory.quantity < quantity_consumed:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"{old_quantity - quantity_remaining} is the minimum as it has been issued",
|
||||
detail=f"{quantity_consumed} is the minimum as it has been issued",
|
||||
)
|
||||
item.batch.quantity_remaining -= old_quantity - new_inventory.quantity
|
||||
item.batch.quantity_remaining = new_inventory.quantity - quantity_consumed
|
||||
item.quantity = new_inventory.quantity
|
||||
if voucher.date != item.batch.name:
|
||||
item.batch.name = voucher.date
|
||||
if voucher.date < item.batch.name:
|
||||
# TODO: check for issued products which might have been in a back date
|
||||
pass
|
||||
item.batch.name = voucher.date
|
||||
item.rate = new_inventory.rate
|
||||
item.batch.rate = new_inventory.rate
|
||||
item.discount = new_inventory.discount
|
||||
@ -258,7 +264,8 @@ def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, new_inventories: Li
|
||||
item.tax = new_inventory.tax
|
||||
item.batch.tax = new_inventory.tax
|
||||
product.price = new_inventory.rate
|
||||
# TODO: Update all references of the batch with the new rates
|
||||
db.flush()
|
||||
fix_single_batch_prices(item.batch_id, db)
|
||||
else:
|
||||
has_been_issued = db.execute(
|
||||
select(func.count(Inventory.id)).where(Inventory.batch_id == item.batch.id, Inventory.id != item.id)
|
||||
@ -272,43 +279,10 @@ def update_inventory(voucher: Voucher, vendor_id: uuid.UUID, new_inventories: Li
|
||||
db.delete(item.batch)
|
||||
db.delete(item)
|
||||
voucher.inventories.remove(item)
|
||||
for new_inventory in new_inventories:
|
||||
product = db.execute(select(Product).where(Product.id == new_inventory.product.id_)).scalar_one()
|
||||
rc_price = rate_contract_price(product.id, vendor_id, voucher.date, db)
|
||||
if rc_price is not None and rc_price != new_inventory.rate:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Product price does not match the Rate Contract price",
|
||||
)
|
||||
if rc_price is not None:
|
||||
new_inventory.tax = 0
|
||||
new_inventory.discount = 0
|
||||
batch = Batch(
|
||||
name=voucher.date,
|
||||
product_id=product.id,
|
||||
quantity_remaining=new_inventory.quantity,
|
||||
rate=new_inventory.rate,
|
||||
tax=new_inventory.tax,
|
||||
discount=new_inventory.discount,
|
||||
)
|
||||
inventory = Inventory(
|
||||
id_=None,
|
||||
product_id=product.id,
|
||||
batch=batch,
|
||||
quantity=new_inventory.quantity,
|
||||
rate=new_inventory.rate,
|
||||
tax=new_inventory.tax,
|
||||
discount=new_inventory.discount,
|
||||
)
|
||||
inventory.voucher_id = voucher.id
|
||||
db.add(batch)
|
||||
inventory.batch_id = batch.id
|
||||
product.price = new_inventory.rate
|
||||
voucher.inventories.append(inventory)
|
||||
db.add(inventory)
|
||||
save_inventories(voucher, vendor_id, new_inventories, db)
|
||||
|
||||
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db):
|
||||
def update_journals(voucher: Voucher, ven: schema_in.AccountLink, db: Session):
|
||||
vendor = db.execute(select(AccountBase).where(AccountBase.id == ven.id_)).scalar_one()
|
||||
journals = {}
|
||||
amount = 0
|
||||
@ -382,3 +356,13 @@ def rate_contract_price(product_id: uuid.UUID, vendor_id: uuid.UUID, date_: date
|
||||
RateContractItem.product_id == product_id, RateContractItem.rate_contract_id.in_(contracts)
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
|
||||
|
||||
def batch_has_older_vouchers(id_: uuid.UUID, date_: date, voucher_id: uuid.UUID, db: Session) -> bool:
|
||||
count_ = db.execute(
|
||||
select(func.count())
|
||||
.join(Batch.inventories)
|
||||
.join(Inventory.voucher)
|
||||
.where(Batch.id == id_, Voucher.date < date_, Voucher.id != voucher_id)
|
||||
).scalar_one()
|
||||
return count_ > 0
|
||||
|
@ -1,7 +1,6 @@
|
||||
import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import List
|
||||
|
||||
import brewman.schemas.input as schema_in
|
||||
@ -27,7 +26,12 @@ from ..schemas.inventory import Inventory as InventorySchema
|
||||
from ..schemas.user import UserToken
|
||||
from . import get_lock_info
|
||||
from .db_image import save_files, update_files
|
||||
from .voucher import blank_voucher, check_voucher_edit_allowed, voucher_info
|
||||
from .voucher import (
|
||||
blank_voucher,
|
||||
check_voucher_edit_allowed,
|
||||
get_batch_quantity,
|
||||
voucher_info,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
@ -210,36 +214,37 @@ def update_voucher(id_: uuid.UUID, data: schema_in.PurchaseIn, user: UserToken,
|
||||
|
||||
|
||||
def update_inventory(voucher: Voucher, new_inventories: List[InventorySchema], db: Session):
|
||||
old_set = set([(i.id, i.product_id) for i in voucher.inventories])
|
||||
new_set = set([(i.id_, i.product.id_) for i in new_inventories if i.id_ is not None])
|
||||
if len(new_set - old_set):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Product cannot be changed",
|
||||
)
|
||||
for it in range(len(voucher.inventories), 0, -1):
|
||||
item = voucher.inventories[it - 1]
|
||||
found = False
|
||||
for j in range(len(new_inventories), 0, -1):
|
||||
new_inventory = new_inventories[j - 1]
|
||||
if new_inventory.id_ == item.id:
|
||||
found = True
|
||||
if item.product_id != new_inventory.product.id_:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Product cannot be changed",
|
||||
)
|
||||
old_quantity = round(Decimal(item.quantity), 2)
|
||||
quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2)
|
||||
if new_inventory.quantity - old_quantity > quantity_remaining:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"{old_quantity + quantity_remaining} is the maximum for {item.product.full_name}.",
|
||||
)
|
||||
if item.batch.name > voucher.date:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Voucher cannot be before {item.product.name.strftime('%d-%b-%Y')}",
|
||||
)
|
||||
item.batch.quantity_remaining -= new_inventory.quantity - old_quantity
|
||||
item.quantity = new_inventory.quantity
|
||||
new_inventories.remove(new_inventory)
|
||||
break
|
||||
if not found:
|
||||
item.batch.quantity_remaining += item.quantity
|
||||
batch = db.execute(select(Batch).where(Batch.id == item.batch_id)).scalar_one()
|
||||
batch_quantity = get_batch_quantity(item.batch_id, voucher.id, db)
|
||||
index = next((idx for (idx, d) in enumerate(new_inventories) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
new_inventory = new_inventories.pop(index)
|
||||
if new_inventory.quantity > batch_quantity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"{batch_quantity} is the maximum for {item.product.full_name}.",
|
||||
)
|
||||
if batch.name > voucher.date:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"Voucher cannot be before {item.product.name.strftime('%d-%b-%Y')}",
|
||||
)
|
||||
item.batch.quantity_remaining = batch_quantity - new_inventory.quantity
|
||||
item.quantity = new_inventory.quantity
|
||||
item.rate = batch.rate
|
||||
item.tax = batch.tax
|
||||
item.discount = batch.discount
|
||||
else:
|
||||
item.batch.quantity_remaining = batch_quantity
|
||||
voucher.inventories.remove(item)
|
||||
db.delete(item)
|
||||
save_inventories(voucher, new_inventories, db)
|
||||
|
@ -97,20 +97,15 @@ async def update_route(
|
||||
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
|
||||
index = next((idx for (idx, d) in enumerate(items) if d.id_ == item.id), None)
|
||||
if index is not None:
|
||||
new_item = items.pop(index)
|
||||
item.product_id = new_item.product.id_
|
||||
item.price = new_item.price
|
||||
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)
|
||||
add_items(rate_contract, items, db)
|
||||
|
||||
|
||||
@router.delete("/{id_}", response_model=RateContractInSchema)
|
||||
|
@ -2,6 +2,7 @@ import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
|
||||
import brewman.schemas.voucher as output
|
||||
|
||||
@ -428,3 +429,15 @@ def check_voucher_edit_allowed(voucher: Voucher, user: UserToken):
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="You are not allowed to edit other user's vouchers",
|
||||
)
|
||||
|
||||
|
||||
def get_batch_quantity(id_: uuid.UUID, voucher_id: Optional[uuid.UUID], db: Session) -> Decimal:
|
||||
query = (
|
||||
select(func.sum(Inventory.quantity * Journal.debit))
|
||||
.join(Inventory.voucher)
|
||||
.join(Voucher.journals)
|
||||
.where(Inventory.batch_id == id_, Journal.cost_centre_id == CostCentre.cost_centre_purchase())
|
||||
)
|
||||
if voucher_id is not None:
|
||||
query = query.where(Voucher.id != voucher_id)
|
||||
return db.execute(query).scalar_one()
|
||||
|
Loading…
Reference in New Issue
Block a user