girishwangikar's picture
Update app.py
4698205 verified
import gradio as gr
from reportlab.lib.pagesizes import A4
from reportlab.platypus import (
SimpleDocTemplate, Table, TableStyle,
Paragraph, Spacer, Image
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from datetime import datetime
import pandas as pd
import os
LOGO_PATH = "assets/logo.png"
# ================= PDF =================
def generate_pdf(shetkari, sauda_date, entries, entity_type):
# Change 1: Dynamic PDF filename based on shetkari name
pdf_filename = f"{shetkari.replace(' ', '_')}_auction_confirmation_slip.pdf"
doc = SimpleDocTemplate(pdf_filename, pagesize=A4)
styles = getSampleStyleSheet()
elements = []
title_style = ParagraphStyle(
"title",
fontSize=16,
alignment=1,
fontName="Helvetica-Bold"
)
center_style = ParagraphStyle(
"center",
alignment=1
)
# ----- HEADER -----
logo = Image(LOGO_PATH, width=80, height=55) if os.path.exists(LOGO_PATH) else ""
header_text = Paragraph(
"<b>Shree Gajanan Cold Storage Pvt. Ltd.</b><br/><br/>"
"<b>Ashirvad Trading Company</b><br/><br/>"
"Tasgaon-Sangli Road, Kavthe Ekand, Sangli<br/><br/>"
"Prasad Vijay Patil - [Contact : 9359533780]",
ParagraphStyle("header", fontSize=16, alignment=1)
)
header = Table([[logo, header_text]], colWidths=[90, 420])
header.setStyle(TableStyle([
("VALIGN", (0, 0), (-1, -1), "MIDDLE")
]))
elements.extend([header, Spacer(1, 12)])
elements.append(Paragraph("Auction Confirmation Slip", title_style))
elements.append(Spacer(1, 12))
# ----- SHETKARI/VENDOR -----
# Change 5: Dynamic label based on entity_type
# Change 6: Increased font size to 14 (similar to Prasad Vijay Patil which is 16)
entity_label = "Shetkari" if entity_type == "Shetkari" else "Vendor"
shetkari_info = Paragraph(
f"<b>{entity_label}:</b> <b>{shetkari}</b> &nbsp;&nbsp;&nbsp;"
f"<b>Sauda Date:</b> {sauda_date}",
ParagraphStyle("shetkari_style", fontSize=14)
)
# Wrap in table to align with main table
info_table = Table([[shetkari_info]], colWidths=[545])
elements.append(info_table)
elements.append(Spacer(1, 10))
# ----- TABLE -----
table_data = [
["Sr.", "Storage Name", "Lot No", "Quantity", "Rate", "Details"]
]
total_qty = 0
for i, e in enumerate(entries, 1):
total_qty += e["quantity"]
table_data.append([
i,
e["storage"],
e["lot"].upper(),
e["quantity"],
Paragraph(f"<b>{e['rate']}</b>", center_style),
e["details"]
])
table_data.append([
"",
"",
Paragraph("<b>Total</b>", center_style),
Paragraph(f"<b>{total_qty}</b>", center_style),
"",
""
])
table = Table(
table_data,
colWidths=[35, 120, 80, 60, 60, 190]
)
table.setStyle(TableStyle([
("GRID", (0, 0), (-1, -1), 1, colors.black),
("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("FONT", (0, 0), (-1, 0), "Helvetica-Bold"),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]))
elements.append(table)
doc.build(elements)
return pdf_filename
# ================= UX LOGIC =================
def add_entry(storage, lot, qty, rate, details, entries, prev_storage, prev_lot, prev_qty, prev_rate):
# Change 2: Use previous storage if empty
if not storage and prev_storage:
storage = prev_storage
# Change 2: Use previous values if empty for lot, qty, rate
if not lot and prev_lot:
lot = prev_lot
if qty is None and prev_qty is not None:
qty = prev_qty
if rate is None and prev_rate is not None:
rate = prev_rate
entries.append({
"storage": storage,
"lot": lot,
"quantity": int(qty),
"details": details,
"rate": float(rate)
})
df = create_display_dataframe(entries)
# Change 2: Return empty/None values for lot, qty, rate to reset them
# Return current values to be stored as "previous"
return entries, storage, lot, qty, rate, df, "", None, None, ""
def create_display_dataframe(entries):
"""Create dataframe with index column for selection"""
if not entries:
return pd.DataFrame(columns=["Select", "Storage", "Lot", "Quantity", "Rate", "Details"])
display_data = []
for i, e in enumerate(entries):
display_data.append({
"Select": i,
"Storage": e["storage"],
"Lot": e["lot"],
"Quantity": e["quantity"],
"Rate": e["rate"],
"Details": e["details"]
})
return pd.DataFrame(display_data)
def delete_entry(row_to_delete, entries):
"""Delete entry by row index"""
if row_to_delete is None or row_to_delete < 0:
return entries, create_display_dataframe(entries), None
if row_to_delete < len(entries):
entries.pop(row_to_delete)
return entries, create_display_dataframe(entries), None
def generate(shetkari, sauda_date, entries, entity_type):
return generate_pdf(shetkari, sauda_date, entries, entity_type)
# ================= UI =================
with gr.Blocks(title="Auction Confirmation Slip") as demo:
gr.Markdown("## 🧾 Create New Auction Confirmation Slip")
with gr.Row():
# Change 5: Added dropdown for entity type selection
entity_type = gr.Dropdown(
choices=["Shetkari", "Vendor"],
value="Shetkari",
label="Entity Type"
)
shetkari = gr.Textbox(label="Shetkari/Vendor Name")
sauda_date = gr.Textbox(
label="Sauda Date",
value=datetime.today().strftime("%d/%m/%Y")
)
entries_state = gr.State([])
prev_storage = gr.State("")
# Change 2: Added state variables for previous lot, qty, rate
prev_lot = gr.State("")
prev_qty = gr.State(None)
prev_rate = gr.State(None)
gr.Markdown("### ➕ Add Entry")
with gr.Row():
storage = gr.Textbox(label="Storage Name (leave empty to reuse)")
# Change 3: Added elem_id for JavaScript to enable caps lock
lot = gr.Textbox(label="Lot Number", elem_id="lot_number_input")
with gr.Row():
qty = gr.Number(label="Quantity", precision=0)
rate = gr.Number(label="Rate")
details = gr.Textbox(
label="Details",
lines=3,
placeholder="Enter detailed description"
)
add_btn = gr.Button("Add Entry")
preview = gr.Dataframe(
headers=["Select", "Storage", "Lot", "Quantity", "Rate", "Details"],
interactive=False,
row_count="dynamic",
label="Entries Preview (Note the 'Select' index number)"
)
gr.Markdown("### 🗑️ Delete Entry")
with gr.Row():
delete_index = gr.Number(
label="Enter row number to delete (from 'Select' column)",
precision=0,
minimum=0
)
delete_btn = gr.Button("Delete Entry")
generate_btn = gr.Button("Confirm & Generate PDF")
pdf_output = gr.File(label="Download PDF")
# Change 2 & 3: Updated add_entry click handler
add_btn.click(
add_entry,
inputs=[storage, lot, qty, rate, details, entries_state, prev_storage, prev_lot, prev_qty, prev_rate],
outputs=[entries_state, prev_storage, prev_lot, prev_qty, prev_rate, preview, lot, qty, rate, details]
)
delete_btn.click(
delete_entry,
inputs=[delete_index, entries_state],
outputs=[entries_state, preview, delete_index]
)
generate_btn.click(
generate,
inputs=[shetkari, sauda_date, entries_state, entity_type],
outputs=pdf_output
)
# Change 3: JavaScript to auto-capitalize lot number input
demo.load(js="""
function() {
const lotInput = document.getElementById('lot_number_input');
if (lotInput) {
lotInput.addEventListener('input', function(e) {
this.value = this.value.toUpperCase();
});
}
}
""")
demo.launch()