import gradio as gr import pandas as pd import tempfile from fpdf import FPDF from datetime import datetime # In-memory database (dictionary) products_db = {} bill_items_db = [] def add_product(name, qty, price): if not name: return gr.update(), gr.update(choices=[]) try: qty = float(qty) if qty else 1.0 price = float(price) if price else 0.0 except Exception: qty = 1.0 price = 0.0 products_db[name] = {"qty": qty, "price": price} df = [[name, products_db[name]["qty"], products_db[name]["price"]] for name in products_db.keys()] choices = list(products_db.keys()) return gr.update(value=df), gr.update(choices=choices) def delete_product(name): if name and name in products_db: del products_db[name] df = [[name, products_db[name]["qty"], products_db[name]["price"]] for name in products_db.keys()] choices = list(products_db.keys()) return gr.update(value=df), gr.update(choices=choices, value=None) def add_to_bill(product_name, quantity): if not product_name or product_name not in products_db: # Return current bill items and empty preview df = [[item["name"], item["quantity"], item["unit_price"], item["total"]] for item in bill_items_db] return gr.update(value=df), "" try: quantity = float(quantity) if quantity else 0.0 except Exception: quantity = 0.0 if quantity <= 0: df = [[item["name"], item["quantity"], item["unit_price"], item["total"]] for item in bill_items_db] return gr.update(value=df), "" product = products_db[product_name] unit_price = product["price"] total = unit_price * quantity bill_items_db.append({ "name": product_name, "quantity": quantity, "unit_price": unit_price, "total": total }) df = [[item["name"], item["quantity"], item["unit_price"], item["total"]] for item in bill_items_db] preview = generate_bill_preview() return gr.update(value=df), preview def clear_bill(): bill_items_db.clear() return gr.update(value=[]), "" def generate_bill_preview(): if not bill_items_db: return "No items in bill" preview = "=" * 60 + "\n" preview += "BILL PREVIEW\n" preview += f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" preview += "=" * 60 + "\n\n" preview += f"{'Product':<20} {'Qty':>8} {'Unit Price':>12} {'Total':>12}\n" preview += "-" * 60 + "\n" grand_total = 0.0 for item in bill_items_db: preview += f"{item['name']:<20} {item['quantity']:>8.2f} {item['unit_price']:>12.2f} {item['total']:>12.2f}\n" grand_total += item['total'] preview += "-" * 60 + "\n" preview += f"{'GRAND TOTAL':<20} {' ':>8} {' ':>12} {grand_total:>12.2f}\n" preview += "=" * 60 + "\n" return preview def generate_bill_pdf(): """Generate PDF bill and return file path""" if not bill_items_db: return None pdf = FPDF() pdf.add_page() pdf.set_font("Arial", "B", 16) pdf.cell(0, 10, "INVOICE", ln=1, align='C') pdf.ln(5) pdf.set_font("Arial", "", 10) pdf.cell(0, 10, f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=1) pdf.ln(5) pdf.set_font("Arial", "B", 11) pdf.cell(70, 10, "Product", 1, 0, 'L') pdf.cell(30, 10, "Qty", 1, 0, 'C') pdf.cell(40, 10, "Unit Price", 1, 0, 'R') pdf.cell(40, 10, "Total", 1, 1, 'R') pdf.set_font("Arial", "", 10) grand_total = 0.0 for item in bill_items_db: pdf.cell(70, 10, item['name'], 1, 0, 'L') pdf.cell(30, 10, f"{item['quantity']:.2f}", 1, 0, 'C') pdf.cell(40, 10, f"{item['unit_price']:.2f}", 1, 0, 'R') pdf.cell(40, 10, f"{item['total']:.2f}", 1, 1, 'R') grand_total += item['total'] pdf.set_font("Arial", "B", 11) pdf.cell(140, 10, "GRAND TOTAL", 1, 0, 'R') pdf.cell(40, 10, f"{grand_total:.2f}", 1, 1, 'R') tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") pdf.output(tmp.name) tmp.close() return tmp.name with gr.Blocks(title="Billing System - A Likitha") as demo: gr.Markdown("# ๐Ÿงพ Billing System - by A Likitha") gr.Markdown("Manage products and generate bills with ease autocalculated with pdf exports!") with gr.Tab("๐Ÿ“ฆ Products"): gr.Markdown("### Add/Update Products") gr.Markdown("Enter product details below. Quantity represents the base unit (e.g., 1 kg, 1 piece, etc.)") with gr.Row(): product_name = gr.Textbox(label="Product Name", placeholder="e.g., Idly, Sugar") product_qty = gr.Number(label="Quantity (Base Unit)", value=1, precision=0) product_price = gr.Number(label="Price per Unit", value=0, precision=2) add_product_btn = gr.Button("โž• Add/Update Product", variant="primary") gr.Markdown("### Product List") product_table = gr.Dataframe( headers=["Name", "Qty", "Price"], datatype=["str", "number", "number"], row_count=0, interactive=False, label="Current Products" ) gr.Markdown("### Delete Product") with gr.Row(): delete_dropdown = gr.Dropdown(choices=[], label="Select Product to Delete") delete_product_btn = gr.Button("๐Ÿ—‘๏ธ Delete Product", variant="stop") add_product_btn.click( fn=add_product, inputs=[product_name, product_qty, product_price], outputs=[product_table, delete_dropdown] ) delete_product_btn.click( fn=delete_product, inputs=[delete_dropdown], outputs=[product_table, delete_dropdown] ) with gr.Tab("๐Ÿ’ฐ Bills"): gr.Markdown("### Create New Bill") gr.Markdown("Select a product and enter the quantity to add to the bill") with gr.Row(): bill_product_dropdown = gr.Dropdown( choices=list(products_db.keys()), label="Select Product" ) bill_quantity = gr.Number(label="Quantity", value=1, precision=2) add_to_bill_btn = gr.Button("โž• Add to Bill", variant="primary") clear_bill_btn = gr.Button("๐Ÿ—‘๏ธ Clear Bill", variant="secondary") gr.Markdown("### Current Bill Items") bill_table = gr.Dataframe( headers=["Product", "Quantity", "Unit Price", "Total"], datatype=["str", "number", "number", "number"], row_count=0, interactive=False, label="Bill Items" ) gr.Markdown("### Bill Preview") bill_preview = gr.Textbox( label="Preview", lines=15, interactive=False, placeholder="Add items to see bill preview..." ) generate_pdf_btn = gr.Button("๐Ÿ“„ Generate & Download PDF", variant="primary", size="lg") pdf_output = gr.File(label="Download Bill PDF") add_to_bill_btn.click( fn=add_to_bill, inputs=[bill_product_dropdown, bill_quantity], outputs=[bill_table, bill_preview] ) clear_bill_btn.click( fn=clear_bill, inputs=[], outputs=[bill_table, bill_preview] ) generate_pdf_btn.click( fn=generate_bill_pdf, inputs=[], outputs=[pdf_output] ) add_product_btn.click( fn=lambda: gr.update(choices=list(products_db.keys())), inputs=[], outputs=[bill_product_dropdown] ) if __name__ == "__main__": demo.launch()