Fix: Check if moved/merged kots could lead to negative products of a situation where happy hour products were more than regular products.

Case:
  Kot 1:
    Beer Mug => 2 regular, 2 happy hour
  Kot 2:
    Beer Mug => 2 Regular
  Kot 3:
    Beer Mug => -2 Regular

Then move Kot 2 to new table would leave the voucher with 2 hh and 0 regular
Also, just move did not check if products were going negative.
This commit is contained in:
Amritanshu Agrawal 2023-03-24 10:17:06 +05:30
parent 5c697dd43a
commit c13047e812
2 changed files with 54 additions and 12 deletions

View File

@ -1,17 +1,16 @@
import uuid import uuid
from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import List, Set from typing import Set
import barker.schemas.voucher as schemas import barker.schemas.voucher as schemas
from barker.models.bill import Bill
from fastapi import HTTPException, status from fastapi import HTTPException, status
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy.sql import expression from sqlalchemy.sql import expression
from ...models.bill import Bill
from ...models.guest_book import GuestBook from ...models.guest_book import GuestBook
from ...models.overview import Overview from ...models.overview import Overview
from ...models.regime import Regime from ...models.regime import Regime

View File

@ -50,7 +50,20 @@ def merge_kot(
.where(Kot.id == data.kot_id, Kot.voucher_id == data.voucher_id) .where(Kot.id == data.kot_id, Kot.voucher_id == data.voucher_id)
.values(voucher_id=data.new_voucher_id) .values(voucher_id=data.new_voucher_id)
) )
update_settlements([data.voucher_id, data.new_voucher_id], db) donor: Voucher = db.execute(select(Voucher).where(Voucher.id == data.voucher_id)).scalar_one()
recipent: Voucher = db.execute(select(Voucher).where(Voucher.id == data.new_voucher_id)).scalar_one()
if has_negatives(donor.kots) or happy_hour_exceeds_regular(donor.kots):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Donor voucher will have negative products or too many happy hours",
)
if has_negatives(recipent.kots) or happy_hour_exceeds_regular(recipent.kots):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Recipient voucher will have negative products or too many happy hours",
)
do_update_settlements(donor, [], db)
do_update_settlements(recipent, [], db)
db.commit() db.commit()
except SQLAlchemyError as e: except SQLAlchemyError as e:
raise HTTPException( raise HTTPException(
@ -91,7 +104,19 @@ def move_kot(
db.flush() db.flush()
do_update_bill_numbers(item, db) do_update_bill_numbers(item, db)
do_update_table(item, None, db) do_update_table(item, None, db)
update_settlements([data.voucher_id, item.id], db) donor: Voucher = db.execute(select(Voucher).where(Voucher.id == data.voucher_id)).scalar_one()
if has_negatives(donor.kots) or happy_hour_exceeds_regular(donor.kots):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Donor voucher will have negative products or too many happy hours",
)
if has_negatives(item.kots) or happy_hour_exceeds_regular(item.kots):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Recipient voucher will have negative products or too many happy hours",
)
do_update_settlements(donor, [], db)
do_update_settlements(item, [], db)
db.commit() db.commit()
except SQLAlchemyError as e: except SQLAlchemyError as e:
raise HTTPException( raise HTTPException(
@ -133,7 +158,8 @@ def merge_table(
db.execute(delete(Overview).where(Overview.voucher_id == data.voucher_id)) db.execute(delete(Overview).where(Overview.voucher_id == data.voucher_id))
db.execute(delete(Settlement).where(Settlement.voucher_id == data.voucher_id)) db.execute(delete(Settlement).where(Settlement.voucher_id == data.voucher_id))
db.execute(delete(Voucher).where(Voucher.id == data.voucher_id)) db.execute(delete(Voucher).where(Voucher.id == data.voucher_id))
update_settlements([data.new_voucher_id], db) recipent: Voucher = db.execute(select(Voucher).where(Voucher.id == data.new_voucher_id)).scalar_one()
do_update_settlements(recipent, [], db)
db.commit() db.commit()
except SQLAlchemyError as e: except SQLAlchemyError as e:
traceback.print_exc() traceback.print_exc()
@ -143,12 +169,6 @@ def merge_table(
) )
def update_settlements(vouchers: list[uuid.UUID], db: Session):
for v in vouchers:
voucher: Voucher = db.execute(select(Voucher).where(Voucher.id == v)).scalar_one()
do_update_settlements(voucher, [], db)
def check_if_voucher_is_unprinted(voucher_id: uuid.UUID, db: Session) -> None: def check_if_voucher_is_unprinted(voucher_id: uuid.UUID, db: Session) -> None:
voucher_type: VoucherType = db.execute(select(Voucher.voucher_type).where(Voucher.id == voucher_id)).scalar_one() voucher_type: VoucherType = db.execute(select(Voucher.voucher_type).where(Voucher.id == voucher_id)).scalar_one()
if voucher_type is None: if voucher_type is None:
@ -161,3 +181,26 @@ def check_if_voucher_is_unprinted(voucher_id: uuid.UUID, db: Session) -> None:
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
detail="Bill is printed or void.", detail="Bill is printed or void.",
) )
def has_negatives(kots: list[Kot]) -> bool:
inv = [i for k in kots for i in k.inventories]
products = set((i.product_id, i.is_happy_hour) for i in inv)
for id_, hh in products:
quantity = sum(i.quantity for i in inv if i.product_id == id_ and i.is_happy_hour == hh)
if quantity < 0:
return True
return False
# This is for the whole bill. eg. Kot 1 => Reg 2 + HH 2; Kot 2 => Reg 4; Kot 3 => Reg - 4
# This is pass okay in happy hours items balanced, but overall this is wrong. Hence this check
def happy_hour_exceeds_regular(kots: list[Kot]) -> bool:
inv = [i for k in kots for i in k.inventories]
products = set(i.product_id for i in inv if i.is_happy_hour)
for p in products:
r = sum(i.quantity for i in inv if i.product_id == p and not i.is_happy_hour)
h = sum(i.quantity for i in inv if i.product_id == p and i.is_happy_hour)
if r < h:
return True
return False