Chore:
Deduplicated the settle options function for save/update/void/receive payment Ported: Void Receive payment
This commit is contained in:
parent
6c06271315
commit
578385f866
@ -26,7 +26,7 @@ from .routers.reports import (
|
||||
sale_report,
|
||||
tax_report
|
||||
)
|
||||
from .routers.voucher import show, save, update
|
||||
from .routers.voucher import show, save, update, receive_payment, void
|
||||
|
||||
from .db.base_class import Base
|
||||
from .core.config import settings
|
||||
@ -72,6 +72,8 @@ app.include_router(guest_book.router, prefix="/api/guest-book", tags=["guest-boo
|
||||
app.include_router(show.router, prefix="/api/voucher", tags=["voucher"])
|
||||
app.include_router(save.router, prefix="/api/voucher", tags=["voucher"])
|
||||
app.include_router(update.router, prefix="/api/voucher", tags=["voucher"])
|
||||
app.include_router(receive_payment.router, prefix="/api/voucher", tags=["voucher"])
|
||||
app.include_router(void.router, prefix="/api/voucher", tags=["voucher"])
|
||||
|
||||
# app.include_router(issue_grid.router, prefix="/api/issue-grid", tags=["vouchers"])
|
||||
# app.include_router(batch.router, prefix="/api/batch", tags=["vouchers"])
|
||||
|
@ -1,4 +1,5 @@
|
||||
import uuid
|
||||
from typing import Optional, List
|
||||
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import func
|
||||
@ -14,6 +15,8 @@ from barker.models import (
|
||||
GuestBook,
|
||||
)
|
||||
|
||||
from barker.schemas.receive_payment import ReceivePaymentItem as SettleSchema
|
||||
|
||||
|
||||
def get_tax(tax, voucher_type):
|
||||
if voucher_type in [VoucherType.STAFF, VoucherType.NO_CHARGE]:
|
||||
@ -39,7 +42,7 @@ def get_bill_id(voucher_type, db):
|
||||
return bill_id
|
||||
|
||||
|
||||
def do_update_table(item, guest_book, db):
|
||||
def do_update_table(item: Voucher, guest_book: Optional[GuestBook], db: Session):
|
||||
status_ = "running" if item.voucher_type == VoucherType.KOT else "printed"
|
||||
if item.status is None:
|
||||
item.status = Overview(
|
||||
@ -53,7 +56,7 @@ def do_update_table(item, guest_book, db):
|
||||
item.status.status = status_
|
||||
|
||||
|
||||
def check_permissions(item, voucher_type, permissions):
|
||||
def check_permissions(item: Optional[Voucher], voucher_type: VoucherType, permissions: List[str]):
|
||||
if voucher_type == VoucherType.KOT and "print-kot" not in permissions:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to print a kot",
|
||||
@ -87,26 +90,31 @@ def get_guest_book(id_: uuid.UUID, db: Session):
|
||||
return db.query(GuestBook).filter(GuestBook.id == id_).first()
|
||||
|
||||
|
||||
def do_update_settlements(voucher, db: Session):
|
||||
settlements = []
|
||||
def do_update_settlements(voucher: Voucher, others: List[SettleSchema], db: Session):
|
||||
settlements: List[SettleSchema] = []
|
||||
settlements += others
|
||||
total_amount = voucher.amount
|
||||
settlements.append({"id": SettleOption.AMOUNT(), "amount": -total_amount})
|
||||
settlements.append(SettleSchema(id=SettleOption.AMOUNT(), amount=-total_amount))
|
||||
round_off = round(total_amount) - total_amount
|
||||
if round_off != 0:
|
||||
settlements.append({"id": SettleOption.ROUND_OFF(), "amount": -round_off})
|
||||
settlements.append({"id": SettleOption.UNSETTLED(), "amount": round(total_amount)})
|
||||
settlements.append(SettleSchema(id=SettleOption.ROUND_OFF(), amount=-round_off))
|
||||
unsettled = sum(x.amount for x in settlements)
|
||||
if len(others) and unsettled != 0: # This should not be allowed
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Payment received is not equal to bill amount",
|
||||
)
|
||||
if unsettled != 0:
|
||||
settlements.append(SettleSchema(id=SettleOption.UNSETTLED(), amount=unsettled))
|
||||
|
||||
for i in settlements:
|
||||
amount = i["amount"]
|
||||
settlement_type_id = i["id"]
|
||||
old = [s for s in voucher.settlements if s.settled == settlement_type_id]
|
||||
old = [s for s in voucher.settlements if s.settled == i.id_]
|
||||
if len(old) == 1:
|
||||
old[0].amount = amount
|
||||
old[0].amount = i.amount
|
||||
else:
|
||||
s = Settlement(voucher.id, settlement_type_id, amount)
|
||||
s = Settlement(voucher.id, i.id_, i.amount)
|
||||
voucher.settlements.append(s)
|
||||
db.add(s)
|
||||
|
||||
for i in (i for i in voucher.settlements if i.settled not in [x["id"] for x in settlements]):
|
||||
for i in (i for i in voucher.settlements if i.settled not in [x.id_ for x in settlements]):
|
||||
voucher.settlements.remove(i)
|
||||
db.delete(i)
|
||||
|
@ -1,63 +1,59 @@
|
||||
import uuid
|
||||
from decimal import Decimal
|
||||
|
||||
import transaction
|
||||
from pyramid.view import view_config
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from barker.models import SettleOption, Voucher, Settlement, Overview, VoucherType
|
||||
from barker.models.validation_exception import ValidationError
|
||||
from . import do_update_settlements
|
||||
from ...schemas.auth import UserToken
|
||||
import barker.schemas.receive_payment as schemas
|
||||
from ...core.security import get_current_active_user as get_user
|
||||
from ...db.session import SessionLocal
|
||||
from ...models import Voucher, VoucherType, SettleOption, Settlement, Overview
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@view_config(
|
||||
request_method="POST",
|
||||
route_name="v1_vouchers_id",
|
||||
renderer="json",
|
||||
request_param="receive-payment",
|
||||
permission="Settle Bill",
|
||||
trans=False,
|
||||
)
|
||||
def receive_payment(request):
|
||||
update_table = request.GET["u"]
|
||||
json = request.json_body
|
||||
amounts = [
|
||||
j
|
||||
for j in json["amounts"]
|
||||
if j["amount"] != 0 and j["id"] not in [SettleOption.AMOUNT(), SettleOption.ROUND_OFF()]
|
||||
]
|
||||
for item in amounts:
|
||||
item["amount"] = round(Decimal(item["amount"]), 0)
|
||||
id_ = uuid.UUID(request.matchdict["id"])
|
||||
item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first()
|
||||
# Dependency
|
||||
def get_db():
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if item.voucher_type in [VoucherType.NO_CHARGE, VoucherType.STAFF]:
|
||||
item.reason = json["name"].strip().title()
|
||||
|
||||
total_amount = item.amount
|
||||
amounts.append({"id": SettleOption.AMOUNT(), "amount": -total_amount})
|
||||
round_off = round(total_amount) - total_amount
|
||||
if round_off != 0:
|
||||
amounts.append({"id": SettleOption.ROUND_OFF(), "amount": -round_off})
|
||||
@router.post("/receive-payment/{id_}")
|
||||
def update(
|
||||
id_: uuid.UUID,
|
||||
data: schemas.ReceivePayment,
|
||||
u: bool, # Update table?
|
||||
db: Session = Depends(get_db),
|
||||
user: UserToken = Security(get_user, scopes=["settle-bill"]),
|
||||
):
|
||||
try:
|
||||
update_table = u
|
||||
amounts = [
|
||||
j for j in data.amounts if j.amount != 0 and j.id_ not in [SettleOption.AMOUNT(), SettleOption.ROUND_OFF()]
|
||||
]
|
||||
for i in amounts:
|
||||
i.amount = round(i.amount, 0)
|
||||
item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
||||
|
||||
if sum([i["amount"] for i in amounts]) != 0:
|
||||
raise ValidationError("Payment received is not equal to bill amount")
|
||||
if item.voucher_type in [VoucherType.NO_CHARGE, VoucherType.STAFF]:
|
||||
item.reason = data.name.title()
|
||||
|
||||
for i in amounts:
|
||||
amount = i["amount"]
|
||||
settlement_type_id = i["id"]
|
||||
old = [s for s in item.settlements if s.settled == settlement_type_id]
|
||||
if len(old) == 1:
|
||||
old[0].amount = amount
|
||||
else:
|
||||
s = Settlement(item.id, settlement_type_id, amount)
|
||||
item.settlements.append(s)
|
||||
request.dbsession.add(s)
|
||||
do_update_settlements(item, amounts, db)
|
||||
|
||||
allowed = [a["id"] for a in amounts]
|
||||
for i in (s for s in item.settlements if s.settled not in allowed):
|
||||
item.settlements.remove(i)
|
||||
request.dbsession.delete(i)
|
||||
|
||||
if update_table:
|
||||
request.dbsession.query(Overview).filter(Overview.voucher_id == item.id).delete()
|
||||
transaction.commit()
|
||||
return True
|
||||
if update_table:
|
||||
db.query(Overview).filter(Overview.voucher_id == item.id).delete()
|
||||
db.commit()
|
||||
return True
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
|
@ -1,6 +1,5 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
@ -90,7 +89,7 @@ def save(
|
||||
mod = InventoryModifier(None, m.id_, 0)
|
||||
inv.modifiers.append(mod)
|
||||
db.add(mod)
|
||||
do_update_settlements(item, db)
|
||||
do_update_settlements(item, [], db)
|
||||
if len(item.kots) == 0 or len(item.kots[0].inventories) == 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Please add some products",
|
||||
|
@ -142,6 +142,6 @@ def voucher_blank(table, guest):
|
||||
"pax": table.seats if guest is None else guest.pax,
|
||||
"table": {"id": table.id, "name": table.name},
|
||||
"voucherType": VoucherType.KOT.name,
|
||||
"customer": {"id": guest.customer_id, "name": guest.customer.name} if guest is not None else {},
|
||||
"customer": {"id": guest.customer_id, "name": guest.customer.name} if guest is not None else None,
|
||||
"kots": [],
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
@ -96,7 +95,7 @@ def update(
|
||||
mod = InventoryModifier(None, m.id_, 0)
|
||||
inv.modifiers.append(mod)
|
||||
db.add(mod)
|
||||
do_update_settlements(item, db)
|
||||
do_update_settlements(item, [], db)
|
||||
if update_table:
|
||||
do_update_table(item, guest_book, db)
|
||||
db.commit()
|
||||
|
@ -1,58 +1,54 @@
|
||||
import uuid
|
||||
|
||||
import transaction
|
||||
from pyramid.view import view_config
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from barker.models import Voucher, SettleOption, Settlement, Overview, VoucherType
|
||||
from . import do_update_settlements
|
||||
from ...schemas.auth import UserToken
|
||||
from ...core.security import get_current_active_user as get_user
|
||||
from ...db.session import SessionLocal
|
||||
from ...models import Voucher, VoucherType, SettleOption, Overview
|
||||
from barker.schemas.receive_payment import ReceivePaymentItem as SettleSchema
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@view_config(
|
||||
request_method="POST",
|
||||
route_name="v1_vouchers_id",
|
||||
renderer="json",
|
||||
request_param="void-bill",
|
||||
permission="Void Bill",
|
||||
trans=True,
|
||||
)
|
||||
def void_voucher(request):
|
||||
id_ = uuid.UUID(request.matchdict["id"])
|
||||
reason = request.json_body["reason"]
|
||||
update_table = request.GET["u"] == "true"
|
||||
|
||||
item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first()
|
||||
|
||||
item.void = True
|
||||
item.reason = reason
|
||||
item.voucher_type = VoucherType.VOID
|
||||
|
||||
do_void_settlements(item, request.dbsession)
|
||||
|
||||
if update_table:
|
||||
request.dbsession.query(Overview).filter(Overview.voucher_id == item.id).delete()
|
||||
transaction.commit()
|
||||
return True
|
||||
# Dependency
|
||||
def get_db():
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def do_void_settlements(item, dbsession):
|
||||
settlements = []
|
||||
total_amount = item.amount
|
||||
settlements.append({"id": SettleOption.AMOUNT(), "amount": -total_amount})
|
||||
round_off = round(total_amount) - total_amount
|
||||
if round_off != 0:
|
||||
settlements.append({"id": SettleOption.ROUND_OFF(), "amount": -round_off})
|
||||
settlements.append({"id": SettleOption.VOID(), "amount": round(total_amount)})
|
||||
@router.post("/void-bill/{id_}")
|
||||
def update(
|
||||
id_: uuid.UUID,
|
||||
u: bool, # Update table?
|
||||
reason: str,
|
||||
db: Session = Depends(get_db),
|
||||
user: UserToken = Security(get_user, scopes=["void-bill"]),
|
||||
):
|
||||
try:
|
||||
item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
||||
|
||||
for i in settlements:
|
||||
amount = i["amount"]
|
||||
settlement_type_id = i["id"]
|
||||
old = [s for s in item.settlements if s.settled == settlement_type_id]
|
||||
if len(old) == 1:
|
||||
old[0].amount = amount
|
||||
else:
|
||||
s = Settlement(item.id, settlement_type_id, amount)
|
||||
item.settlements.append(s)
|
||||
dbsession.add(s)
|
||||
item.void = True
|
||||
item.reason = reason
|
||||
item.voucher_type = VoucherType.VOID
|
||||
|
||||
for i in (i for i in item.settlements if i.settled not in [x["id"] for x in settlements]):
|
||||
item.settlements.remove(i)
|
||||
dbsession.delete(i)
|
||||
do_update_settlements(item, [SettleSchema(id=SettleOption.VOID(), amount=round(item.amount))], db)
|
||||
|
||||
if u: # Update table
|
||||
db.query(Overview).filter(Overview.voucher_id == item.id).delete()
|
||||
db.commit()
|
||||
return True
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
|
29
barker/schemas/receive_payment.py
Normal file
29
barker/schemas/receive_payment.py
Normal file
@ -0,0 +1,29 @@
|
||||
import uuid
|
||||
from typing import Optional, List
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from barker.schemas import to_camel
|
||||
from barker.schemas.customer import CustomerLink
|
||||
from barker.schemas.modifier import ModifierLink
|
||||
from barker.schemas.product import ProductLink
|
||||
from barker.schemas.table import TableLink
|
||||
from barker.schemas.tax import TaxLink
|
||||
|
||||
|
||||
class ReceivePaymentItem(BaseModel):
|
||||
id_: int
|
||||
amount: Decimal
|
||||
|
||||
class Config:
|
||||
fields = {"id_": "id"}
|
||||
|
||||
|
||||
class ReceivePayment(BaseModel):
|
||||
name: str
|
||||
amounts: List[ReceivePaymentItem]
|
||||
|
||||
class Config:
|
||||
alias_generator = to_camel
|
||||
anystr_strip_whitespace = True
|
@ -26,7 +26,7 @@
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="table-details">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-50 bold right-align">{{ bs.bill.table.name }}
|
||||
/ {{ bs.bill.pax }} / {{ bs.bill.customer.name }}</mat-header-cell>
|
||||
/ {{ bs.bill.pax }} / {{ bs.bill.customer?.name }}</mat-header-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Checkbox Column -->
|
||||
|
@ -13,7 +13,7 @@ import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component'
|
||||
import { TableService } from '../../tables/table.service';
|
||||
import { ToasterService } from '../../core/toaster.service';
|
||||
import { AuthService } from '../../auth/auth.service';
|
||||
import { PaxComponent } from "../pax/pax.component";
|
||||
import { PaxComponent } from '../pax/pax.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bills',
|
||||
@ -46,8 +46,8 @@ export class BillsComponent implements OnInit {
|
||||
}
|
||||
|
||||
getPax(): void {
|
||||
if (this.bs.bill.id || this.bs.bill.customer.id) {
|
||||
return
|
||||
if (this.bs.bill.id || this.bs.bill.customer) {
|
||||
return;
|
||||
}
|
||||
const dialogRef = this.dialog.open(PaxComponent, {
|
||||
// width: '750px',
|
||||
|
@ -76,19 +76,24 @@ export class VoucherService {
|
||||
}
|
||||
}
|
||||
|
||||
receivePayment(id: string, amounts: { id: number; name: string; amount: number }[], name: string, updateTable: boolean): Observable<boolean> {
|
||||
const options = {params: new HttpParams().set('receive-payment', '').set('u', updateTable.toString())};
|
||||
receivePayment(
|
||||
id: string,
|
||||
amounts: { id: number; name: string; amount: number }[],
|
||||
name: string,
|
||||
updateTable: boolean
|
||||
): Observable<boolean> {
|
||||
const options = {params: new HttpParams().set('u', updateTable.toString())};
|
||||
return <Observable<boolean>>this.http.post<boolean>(
|
||||
`${url}/${id}`, {name: name, amounts: amounts}, options
|
||||
`${url}/receive-payment/${id}`, {name: name, amounts: amounts}, options
|
||||
).pipe(
|
||||
catchError(this.log.handleError(serviceName, 'receivePayment'))
|
||||
);
|
||||
}
|
||||
|
||||
voidBill(id: string, reason: string, updateTable: boolean): Observable<boolean> {
|
||||
const options = {params: new HttpParams().set('void-bill', '').set('u', updateTable.toString())};
|
||||
const options = {params: new HttpParams().set('reason', reason).set('u', updateTable.toString())};
|
||||
return <Observable<boolean>>this.http.post<boolean>(
|
||||
`${url}/${id}`, {reason: reason}, options
|
||||
`${url}/void-bill/${id}`, {}, options
|
||||
).pipe(
|
||||
catchError(this.log.handleError(serviceName, 'voidBill'))
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user