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:
Amritanshu Agrawal 2020-10-01 11:43:43 +05:30
parent aaac5efea2
commit 3f2a06c2cf
9 changed files with 203 additions and 82 deletions

View File

@ -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"],

View File

@ -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
View 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
View 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)

View File

@ -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]),
)
)

View File

@ -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(

View File

@ -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
View 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

View File

@ -7,7 +7,8 @@
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
"e2e": "ng e2e",
"postinstall": "ngcc"
},
"private": true,
"dependencies": {