Feature:
Print kot and print bill are working now using celery Now also need to install RabbitMQ for clery to work
This commit is contained in:
parent
aaac5efea2
commit
3f2a06c2cf
@ -205,7 +205,7 @@ def upgrade():
|
||||
sa.Column("menu_category_id", postgresql.UUID(), nullable=True),
|
||||
sa.Column("section_id", postgresql.UUID(), nullable=False),
|
||||
sa.Column("printer_id", postgresql.UUID(), nullable=False),
|
||||
sa.Column("copies", sa.Numeric(), nullable=False),
|
||||
sa.Column("copies", sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["menu_category_id"],
|
||||
["menu_categories.id"],
|
||||
|
@ -1,78 +1,3 @@
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import uuid
|
||||
from barker.printing.bill import print_bill # noqa: F401
|
||||
from barker.printing.kot import print_kot # noqa: F401
|
||||
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from barker.models import SectionPrinter, Printer, Voucher
|
||||
|
||||
|
||||
def sent_to_printer(data, address, cut_code):
|
||||
print(data, address, cut_code)
|
||||
try:
|
||||
regex = re.compile(r'pdl://(?P<host>[\w\d.-]+):(?P<port>[\d]+)')
|
||||
match = regex.match(address)
|
||||
s = socket.socket()
|
||||
s.connect((match.group("host"), int(match.group("port"))))
|
||||
s.send(bytearray(data + cut_code, "ascii"))
|
||||
except LookupError as e:
|
||||
print("Lookup error:", e)
|
||||
except:
|
||||
print("Unexpected error:", sys.exc_info()[0])
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def design_kot(voucher, kot, items, copy_number):
|
||||
s = (
|
||||
f"KOT / BOT".center(42)
|
||||
+ "\n\r" + f"Copy No. {copy_number}:".center(42)
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
+ "\n\r" + f"KOT ID : K-{voucher.kot_id:>5}/S-{kot.code:>5} {kot.date:%d-%b-%Y %H:%M}"
|
||||
+ "\n\r" + f"Table No.: {voucher.food_table.name}"
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
+ "\n\r" + " Qty. x Name "
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
)
|
||||
for item in items:
|
||||
name = (
|
||||
"H H " + item.product.full_name
|
||||
if item.is_happy_hour
|
||||
else item.product.full_name
|
||||
)
|
||||
s += "\n\r" + f"{item.quantity:6.2} x {name:>33}"
|
||||
for m in item.modifiers:
|
||||
s += "\n\r" + f" --- {m.name:>32}"
|
||||
s += "\n\r" + "".ljust(42, "-")
|
||||
return s
|
||||
|
||||
|
||||
def print_kot(voucher_id: uuid.UUID, db: Session):
|
||||
voucher: Voucher = db.query(Voucher).filter(Voucher.id == voucher_id).first()
|
||||
my_hash = {}
|
||||
kot = voucher.kots[-1]
|
||||
for item in kot.inventories:
|
||||
printer, copies = (
|
||||
db.query(Printer, SectionPrinter.copies)
|
||||
.join(SectionPrinter.printer)
|
||||
.filter(SectionPrinter.section_id == voucher.food_table.section_id)
|
||||
.filter(
|
||||
or_(
|
||||
SectionPrinter.menu_category_id == item.product.menu_category_id,
|
||||
SectionPrinter.menu_category_id == None,
|
||||
)
|
||||
).order_by(SectionPrinter.menu_category_id)
|
||||
.first()
|
||||
)
|
||||
key = (printer.id, copies)
|
||||
if key not in my_hash:
|
||||
my_hash[key] = (printer, [])
|
||||
my_hash[key][1].append(item)
|
||||
for key, value in my_hash.items():
|
||||
printer_id, copies = key
|
||||
printer, items = value
|
||||
for c in range(int(copies)):
|
||||
data = design_kot(voucher, kot, items, c)
|
||||
sent_to_printer(data, printer.address, printer.cut_code)
|
||||
|
97
barker/printing/bill.py
Normal file
97
barker/printing/bill.py
Normal file
@ -0,0 +1,97 @@
|
||||
import uuid
|
||||
from decimal import Decimal
|
||||
from typing import List, Tuple
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from barker.models import SectionPrinter, Printer, Voucher, Inventory, DbSetting, VoucherType
|
||||
from barker.worker import sent_to_printer
|
||||
|
||||
|
||||
def print_bill(voucher_id: uuid.UUID, db: Session):
|
||||
voucher: Voucher = db.query(Voucher).filter(Voucher.id == voucher_id).first()
|
||||
|
||||
printer = (
|
||||
db.query(Printer)
|
||||
.join(SectionPrinter.printer)
|
||||
.filter(SectionPrinter.section_id == voucher.food_table.section_id)
|
||||
.filter(SectionPrinter.menu_category_id == None)
|
||||
.first()
|
||||
)
|
||||
|
||||
items_dict = {}
|
||||
tax = {}
|
||||
for i in [i for k in voucher.kots for i in k.inventories]:
|
||||
key = (i.product_id, i.is_happy_hour, tuple(m.modifier_id for m in i.modifiers if m.modifier.show_in_bill))
|
||||
if key in items_dict:
|
||||
items_dict[key].quantity += i.quantity
|
||||
else:
|
||||
items_dict[key] = i
|
||||
if i.tax_id in tax:
|
||||
tax[i.tax_id] = (i.tax.name, tax[i.tax_id][1] + i.tax_amount)
|
||||
else:
|
||||
tax[i.tax_id] = (i.tax.name, i.tax_amount)
|
||||
data = design_bill(voucher, items_dict.values(), tax.values(), db)
|
||||
sent_to_printer.delay(data, printer.address, printer.cut_code)
|
||||
|
||||
|
||||
def design_bill(voucher: Voucher, items: List[Tuple[Inventory, Decimal]], tax: List[Tuple[str, Decimal]], db: Session):
|
||||
# Header
|
||||
s = "\n\r" + db.query(DbSetting).filter(DbSetting.name == "Header").first().data['Text']
|
||||
if voucher.voucher_type == VoucherType.REGULAR_BILL:
|
||||
s += "\n\r" + "Retail Invoice".center(42)
|
||||
s += "\n\r"
|
||||
elif voucher.voucher_type == VoucherType.NO_CHARGE:
|
||||
s += "\n\r" + "NO CHARGE - THIS IS NOT A BILL - DON'T PAY".center(42)
|
||||
s += "\n\r"
|
||||
elif voucher.voucher_type == VoucherType.STAFF:
|
||||
s += "\n\r" + "STAFF CONSUMPTION -- THIS IS NOT A BILL".center(42)
|
||||
s += "\n\r"
|
||||
|
||||
# Products
|
||||
s += "\n\r" + f"Bill No: {voucher.full_bill_id:>12} {voucher.date:%d-%b-%Y %H:%M}"
|
||||
s += "\n\r" + "Table No.: " + voucher.food_table.name
|
||||
s += "\n\r" + "-" * 42
|
||||
s += "\n\r" + "Qty. Particulars Price Amount"
|
||||
s += "\n\r" + "-" * 42
|
||||
for item in [i for i in items if i.quantity != 0]:
|
||||
name = "H H " + item.product.full_name if item.is_happy_hour else item.product.full_name
|
||||
s += "\n\r" + f"{item.quantity: >5.2f} {name:<22.22} {item.price: >6.2f} {item.price * item.quantity: >6.2f}"
|
||||
for m in [m for m in item.modifiers if m.modifier.show_in_bill]:
|
||||
s += f"\n\r -- {m.modifier.name: <38.38}"
|
||||
s += "\n\r" + "------------------------------------------"
|
||||
|
||||
# Totals
|
||||
amount = sum(i.quantity * i.price for i in items)
|
||||
s += f"\n\r{'Subtotal :': >32} {amount: >9.2f}"
|
||||
|
||||
amount = sum(i.quantity * i.price for i in items if i.is_happy_hour)
|
||||
if amount != 0:
|
||||
s += f"\n\r{'Happy Hour Discount :': >32} {amount: >9.2f}"
|
||||
|
||||
amount = sum(i.quantity * i.effective_price * i.discount for i in items)
|
||||
if amount != 0:
|
||||
s += f"\n\r{'Discount :': >32} {amount: >9.2f}"
|
||||
|
||||
for t in tax:
|
||||
if t[1] != 0:
|
||||
s += f"\n\r{t[0]: >30} : {t[1]: >9.2f}"
|
||||
|
||||
s += f"\n\r{'Total Amount :',32} {round(voucher.amount): >9.2f}"
|
||||
s += "\n\r" + "-" * 42
|
||||
|
||||
if voucher.voucher_type != VoucherType.REGULAR_BILL:
|
||||
s += "\n\r" + "THIS IS NOT A BILL - DON'T PAY".center(42)
|
||||
s += "\n\r" + "-" * 42
|
||||
|
||||
if voucher.narration:
|
||||
s += f"\n\r{voucher.narration: ^42}"
|
||||
s += "\n\r" + "-" * 42
|
||||
|
||||
if voucher.customer:
|
||||
s += f"\n\r{voucher.customer.name}\n\r{voucher.customer.phone}\n\r{voucher.customer.address}"
|
||||
s += "\n\r" + "-" * 42
|
||||
|
||||
s += "\n\r" + "Cashier : " + voucher.user.name
|
||||
s += "\n\r" + db.query(DbSetting).filter(DbSetting.name == "Footer").first().data['Text']
|
||||
return s
|
61
barker/printing/kot.py
Normal file
61
barker/printing/kot.py
Normal file
@ -0,0 +1,61 @@
|
||||
import uuid
|
||||
from typing import List
|
||||
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from barker.models import SectionPrinter, Printer, Voucher, Kot, Inventory
|
||||
from barker.worker import sent_to_printer
|
||||
|
||||
|
||||
def design_kot(voucher: Voucher, kot: Kot, items: List[Inventory], copy_number: int) -> str:
|
||||
s = (
|
||||
f"KOT / BOT".center(42)
|
||||
+ "\n\r" + f"Copy No. {copy_number}:".center(42)
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
+ "\n\r" + f"KOT ID : K-{voucher.kot_id:>5}/S-{kot.code:>5} {kot.date:%d-%b-%Y %H:%M}"
|
||||
+ "\n\r" + f"Table No.: {voucher.food_table.name}"
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
+ "\n\r" + " Qty. x Name "
|
||||
+ "\n\r" + "".ljust(42, "-")
|
||||
)
|
||||
for item in items:
|
||||
name = (
|
||||
"H H " + item.product.full_name
|
||||
if item.is_happy_hour
|
||||
else item.product.full_name
|
||||
)
|
||||
s += "\n\r" + f"{item.quantity:6.2} x {name:>33}"
|
||||
for m in item.modifiers:
|
||||
s += "\n\r" + f" --- {m.name:>32}"
|
||||
s += "\n\r" + "".ljust(42, "-")
|
||||
return s
|
||||
|
||||
|
||||
def print_kot(voucher_id: uuid.UUID, db: Session):
|
||||
voucher: Voucher = db.query(Voucher).filter(Voucher.id == voucher_id).first()
|
||||
my_hash = {}
|
||||
kot: Kot = voucher.kots[-1]
|
||||
for item in kot.inventories:
|
||||
printer, copies = (
|
||||
db.query(Printer, SectionPrinter.copies)
|
||||
.join(SectionPrinter.printer)
|
||||
.filter(SectionPrinter.section_id == voucher.food_table.section_id)
|
||||
.filter(
|
||||
or_(
|
||||
SectionPrinter.menu_category_id == item.product.menu_category_id,
|
||||
SectionPrinter.menu_category_id == None,
|
||||
)
|
||||
).order_by(SectionPrinter.menu_category_id)
|
||||
.first()
|
||||
)
|
||||
key = (printer.id, copies)
|
||||
if key not in my_hash:
|
||||
my_hash[key] = (printer, [])
|
||||
my_hash[key][1].append(item)
|
||||
for key, value in my_hash.items():
|
||||
printer_id, copies = key
|
||||
printer, items = value
|
||||
for c in range(int(copies)):
|
||||
data = design_kot(voucher, kot, items, c)
|
||||
sent_to_printer.delay(data, printer.address, printer.cut_code)
|
@ -59,6 +59,7 @@ def save(
|
||||
SectionPrinter.__table__.delete(
|
||||
and_(
|
||||
SectionPrinter.section_id == id_,
|
||||
SectionPrinter.menu_category_id != None,
|
||||
~SectionPrinter.menu_category_id.in_([x for x in current if x is not None]),
|
||||
)
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ from ...routers.voucher import (
|
||||
check_permissions,
|
||||
get_guest_book,
|
||||
)
|
||||
from barker.printing import print_kot
|
||||
from barker.printing import print_kot, print_bill
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@ -51,8 +51,9 @@ def save(
|
||||
if update_table:
|
||||
do_update_table(item, guest_book, db)
|
||||
db.commit()
|
||||
# print_kot(item.id, db)
|
||||
|
||||
print_kot(item.id, db)
|
||||
if item.voucher_type != VoucherType.KOT:
|
||||
print_bill(item.id, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
|
@ -7,6 +7,7 @@ from sqlalchemy import func
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ...printing import print_kot, print_bill
|
||||
from ...schemas.auth import UserToken
|
||||
import barker.schemas.voucher as schemas
|
||||
from ...core.security import get_current_active_user as get_user
|
||||
@ -48,6 +49,7 @@ def update(
|
||||
update_table = u
|
||||
voucher_type = VoucherType[p]
|
||||
guest_book = get_guest_book(g, db)
|
||||
need_to_print_kot = False
|
||||
|
||||
item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
||||
|
||||
@ -76,6 +78,7 @@ def update(
|
||||
round(inv.discount, 5) for ko in data.kots for inv in ko.inventories if inv.id_ == i.id
|
||||
)
|
||||
for k in (k for k in data.kots if k.id_ is None and len(k.inventories) > 0):
|
||||
need_to_print_kot = True
|
||||
code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar()
|
||||
kot = Kot(item.id, code, item.food_table_id, now, item.user_id)
|
||||
item.kots.append(kot)
|
||||
@ -104,6 +107,10 @@ def update(
|
||||
if update_table:
|
||||
do_update_table(item, guest_book, db)
|
||||
db.commit()
|
||||
if need_to_print_kot:
|
||||
print_kot(item.id, db)
|
||||
if item.voucher_type != VoucherType.KOT:
|
||||
print_bill(item.id, db)
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
|
28
barker/worker.py
Normal file
28
barker/worker.py
Normal file
@ -0,0 +1,28 @@
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
from celery import Celery
|
||||
from celery.utils.log import get_task_logger
|
||||
|
||||
# Create the celery app and get the logger
|
||||
celery_app = Celery('tasks', broker='pyamqp://guest@localhost//')
|
||||
logger = get_task_logger(__name__)
|
||||
|
||||
|
||||
@celery_app.task
|
||||
def sent_to_printer(data: str, address: str, cut_code: str):
|
||||
print(data, address, cut_code)
|
||||
# try:
|
||||
# regex = re.compile(r'pdl://(?P<host>[\w\d.-]+):(?P<port>[\d]+)')
|
||||
# match = regex.match(address)
|
||||
# s = socket.socket()
|
||||
# s.connect((match.group("host"), int(match.group("port"))))
|
||||
# s.send(bytearray(data + cut_code, "ascii"))
|
||||
# except LookupError as e:
|
||||
# print("Lookup error:", e)
|
||||
# except:
|
||||
# print("Unexpected error:", sys.exc_info()[0])
|
||||
# finally:
|
||||
# s.close()
|
||||
|
||||
# celery --app=barker.worker.celery_app worker -c 2 --loglevel=INFO
|
@ -7,7 +7,8 @@
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
"e2e": "ng e2e",
|
||||
"postinstall": "ngcc"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user