Ledger_Tracking / delete_tab.py
girishwangikar's picture
Update delete_tab.py
fd9f7d5 verified
import gradio as gr
import pandas as pd
import os
class DeleteTab:
def __init__(self, get_sheet_func, get_farmers_func, format_indian_currency_func, format_date_display_func):
"""
Initialize the Delete Tab
Args:
get_sheet_func: Function to get Google Sheet
get_farmers_func: Function to get list of farmers
format_indian_currency_func: Function to format currency in Indian style
format_date_display_func: Function to format date display
"""
self.get_sheet = get_sheet_func
self.get_farmers = get_farmers_func
self.format_indian_currency = format_indian_currency_func
self.format_date_display = format_date_display_func
def refresh_farmers(self):
"""Refresh farmer dropdown"""
return gr.Dropdown(choices=self.get_farmers())
def get_farmer_transactions_for_deletion(self, farmer_name):
"""Get all transactions for a farmer with row indices"""
try:
if not farmer_name or not farmer_name.strip():
return None, "❌ Please select a farmer"
farmer_name = farmer_name.strip()
spreadsheet = self.get_sheet()
trans_sheet = spreadsheet.worksheet("Transactions")
data = trans_sheet.get_all_values()
if len(data) <= 1:
return None, f"❌ No transactions found for farmer '{farmer_name}'"
# Create DataFrame with row indices
df = pd.DataFrame(data[1:], columns=data[0])
df['Sheet_Row'] = range(2, len(data) + 1)
# Filter by farmer
farmer_df = df[df['Farmer Name'] == farmer_name].copy()
if farmer_df.empty:
return None, f"❌ No transactions found for farmer '{farmer_name}'"
# Convert amount and date
farmer_df['Amount'] = pd.to_numeric(farmer_df['Amount'], errors='coerce')
farmer_df['Date'] = pd.to_datetime(farmer_df['Date'], errors='coerce')
farmer_df = farmer_df.sort_values('Date')
# Create display dataframe
display_df = farmer_df[['Sheet_Row', 'Date', 'Type', 'Bank Account', 'Amount']].copy()
display_df.columns = ['Row #', 'Date', 'Description', 'Bank Account', 'Amount (β‚Ή)']
display_df['Date'] = display_df['Date'].apply(lambda x: self.format_date_display(str(x)[:10]))
display_df['Amount (β‚Ή)'] = display_df['Amount (β‚Ή)'].apply(self.format_indian_currency)
return display_df, f"βœ… Found {len(farmer_df)} transaction(s) for {farmer_name}"
except Exception as e:
import traceback
traceback.print_exc()
return None, f"❌ Error loading transactions: {str(e)}"
def delete_single_transaction(self, row_number):
"""Delete a single transaction by row number"""
try:
if not row_number:
return "❌ Please select a row to delete"
row_number = int(row_number)
spreadsheet = self.get_sheet()
trans_sheet = spreadsheet.worksheet("Transactions")
# Delete the row
trans_sheet.delete_rows(row_number)
return f"βœ… Successfully deleted transaction at row {row_number}"
except Exception as e:
return f"❌ Error deleting transaction: {str(e)}"
def delete_all_farmer_data(self, farmer_name):
"""Delete all data for a farmer including transactions and farmer registration"""
try:
if not farmer_name or not farmer_name.strip():
return "❌ Please enter a farmer name"
farmer_name = farmer_name.strip()
spreadsheet = self.get_sheet()
# 1. Delete all transactions for this farmer
trans_sheet = spreadsheet.worksheet("Transactions")
data = trans_sheet.get_all_values()
if len(data) > 1:
# Find rows to delete (from bottom to top to avoid index shifting)
rows_to_delete = []
for idx, row in enumerate(data[1:], start=2):
if len(row) > 1 and row[1] == farmer_name: # Column 1 is Farmer Name
rows_to_delete.append(idx)
# Delete rows from bottom to top
for row_num in sorted(rows_to_delete, reverse=True):
trans_sheet.delete_rows(row_num)
transactions_deleted = len(rows_to_delete)
else:
transactions_deleted = 0
# 2. Remove farmer from metadata
meta_sheet = spreadsheet.worksheet("Metadata")
meta_data = meta_sheet.get_all_values()
for idx, row in enumerate(meta_data):
if len(row) >= 2 and row[0] == 'farmer':
current_farmers = row[1]
farmers_list = [f.strip() for f in current_farmers.split(',') if f.strip()]
if farmer_name in farmers_list:
farmers_list.remove(farmer_name)
new_farmers = ','.join(farmers_list)
meta_sheet.update_cell(idx + 1, 2, new_farmers)
return f"βœ… Successfully deleted farmer '{farmer_name}' from system.\n" \
f"Deleted {transactions_deleted} transaction(s).\n" \
f"Removed farmer from registration list."
if transactions_deleted > 0:
return f"⚠️ Deleted {transactions_deleted} transaction(s) but farmer was not found in registration list"
else:
return f"❌ Farmer '{farmer_name}' not found in system"
except Exception as e:
import traceback
traceback.print_exc()
return f"❌ Error deleting farmer data: {str(e)}"
def get_banks(self):
"""Get list of registered bank accounts"""
try:
spreadsheet = self.get_sheet()
meta_sheet = spreadsheet.worksheet("Metadata")
data = meta_sheet.get_all_values()
banks = []
for row in data:
if len(row) >= 2 and row[0] == 'bank' and row[1]:
banks.extend([b.strip() for b in row[1].split(',') if b.strip()])
return sorted(list(set(banks)))
except Exception as e:
print(f"Error getting banks: {str(e)}")
return []
def refresh_banks(self):
"""Refresh bank dropdown"""
return gr.Dropdown(choices=self.get_banks())
def delete_bank(self, bank_name):
"""Delete a bank from the registration list"""
try:
if not bank_name or not bank_name.strip():
return "❌ Please select a bank account"
bank_name = bank_name.strip()
spreadsheet = self.get_sheet()
meta_sheet = spreadsheet.worksheet("Metadata")
meta_data = meta_sheet.get_all_values()
for idx, row in enumerate(meta_data):
if len(row) >= 2 and row[0] == 'bank':
current_banks = row[1]
banks_list = [b.strip() for b in current_banks.split(',') if b.strip()]
if bank_name in banks_list:
banks_list.remove(bank_name)
new_banks = ','.join(banks_list)
meta_sheet.update_cell(idx + 1, 2, new_banks)
return f"βœ… Successfully deleted bank account '{bank_name}' from registration list"
return f"❌ Bank account '{bank_name}' not found in registration list"
except Exception as e:
import traceback
traceback.print_exc()
return f"❌ Error deleting bank: {str(e)}"
def clear_delete_bank(self):
"""Clear bank deletion interface"""
return ""
def clear_delete_single(self):
"""Clear single deletion interface"""
return None, "", ""
def clear_delete_all(self):
"""Clear complete deletion interface"""
return ""
def create_tab(self):
"""Create the Delete tab interface"""
with gr.Tab("πŸ—‘οΈ Delete Records"):
gr.Markdown("## Delete Transaction Records")
gr.Markdown("⚠️ **Warning**: Deletion is permanent and cannot be undone!")
# Section 1: Delete Single Transaction
with gr.Accordion("πŸ” Delete Individual Transaction", open=False):
gr.Markdown("*Search for a farmer and delete specific transactions*")
with gr.Row():
delete_single_farmer = gr.Dropdown(
label="Select Farmer",
choices=[],
allow_custom_value=True,
scale=9
)
refresh_delete_single_btn = gr.Button("πŸ”„", scale=1, size="sm")
load_delete_trans_btn = gr.Button("Load Transactions", variant="primary")
delete_single_status = gr.Textbox(label="Status", interactive=False, show_label=False)
delete_trans_df = gr.Dataframe(
label="Transactions for Selected Farmer",
interactive=False,
wrap=True
)
gr.Markdown("### Select Transaction to Delete")
gr.Markdown("*Enter the Row # from the table above*")
with gr.Row():
delete_row_input = gr.Textbox(
label="Enter Row Number to Delete",
placeholder="e.g., 15",
scale=3
)
delete_single_btn = gr.Button("Delete Selected Row", variant="stop", size="lg", scale=1)
delete_result = gr.Textbox(label="Deletion Result", interactive=False)
gr.Markdown("---")
# Section 2: Delete All Farmer Data
with gr.Accordion("⚠️ Delete All Farmer Data", open=False):
gr.Markdown("*Permanently delete ALL transactions and registration for a farmer*")
gr.Markdown("**This will:**")
gr.Markdown("- Delete all transaction records for this farmer")
gr.Markdown("- Remove farmer from the registration list")
gr.Markdown("- **Cannot be undone!**")
with gr.Row():
delete_all_farmer = gr.Dropdown(
label="Select Farmer to Delete Completely",
choices=[],
allow_custom_value=True,
scale=9
)
refresh_delete_all_btn = gr.Button("πŸ”„", scale=1, size="sm")
delete_all_confirm = gr.Checkbox(
label="I understand this action is permanent and cannot be undone",
value=False
)
delete_all_btn = gr.Button(
"Delete All Data for This Farmer",
variant="stop",
size="lg"
)
delete_all_result = gr.Textbox(label="Deletion Result", interactive=False)
with gr.Accordion("🏦 Delete Bank Account", open=False):
gr.Markdown("*Remove a bank account from the registration list*")
gr.Markdown("⚠️ **Note**: This only removes the bank from the dropdown list. Existing transactions with this bank will remain.")
with gr.Row():
delete_bank_dropdown = gr.Dropdown(
label="Select Bank Account to Delete",
choices=[],
allow_custom_value=True,
scale=9
)
refresh_delete_bank_btn = gr.Button("πŸ”„", scale=1, size="sm")
delete_bank_confirm = gr.Checkbox(
label="I confirm I want to delete this bank account from the registration list",
value=False
)
delete_bank_btn = gr.Button(
"Delete Bank Account",
variant="stop",
size="lg"
)
delete_bank_result = gr.Textbox(label="Deletion Result", interactive=False)
# Event handlers - Delete Single Transaction
refresh_delete_single_btn.click(
fn=self.refresh_farmers,
outputs=[delete_single_farmer]
)
load_delete_trans_btn.click(
fn=self.get_farmer_transactions_for_deletion,
inputs=[delete_single_farmer],
outputs=[delete_trans_df, delete_single_status]
)
# Replace the delete_single_btn.click handler:
def delete_and_refresh(row_number, farmer_name):
"""Delete transaction and refresh the list"""
if not row_number or not row_number.strip():
return "❌ Please enter a row number", None, ""
result = self.delete_single_transaction(row_number.strip())
# Reload transactions after deletion if deletion was successful
if "Successfully deleted" in result:
new_df, new_status = self.get_farmer_transactions_for_deletion(farmer_name)
return result, new_df, new_status
else:
return result, None, ""
delete_single_btn.click(
fn=delete_and_refresh,
inputs=[delete_row_input, delete_single_farmer],
outputs=[delete_result, delete_trans_df, delete_single_status]
)
# Event handlers - Delete All Farmer Data
refresh_delete_all_btn.click(
fn=self.refresh_farmers,
outputs=[delete_all_farmer]
)
# Event handlers - Delete Bank Account
refresh_delete_bank_btn.click(
fn=self.refresh_banks,
outputs=[delete_bank_dropdown]
)
def delete_bank_with_confirmation(bank_name, confirmed):
if not confirmed:
return "❌ Please check the confirmation box to proceed with deletion"
return self.delete_bank(bank_name)
delete_bank_btn.click(
fn=delete_bank_with_confirmation,
inputs=[delete_bank_dropdown, delete_bank_confirm],
outputs=[delete_bank_result]
).then(
fn=lambda: False, # Uncheck the confirmation box
outputs=[delete_bank_confirm]
)
def delete_all_with_confirmation(farmer_name, confirmed):
if not confirmed:
return "❌ Please check the confirmation box to proceed with deletion"
return self.delete_all_farmer_data(farmer_name)
delete_all_btn.click(
fn=delete_all_with_confirmation,
inputs=[delete_all_farmer, delete_all_confirm],
outputs=[delete_all_result]
).then(
fn=lambda: False, # Uncheck the confirmation box
outputs=[delete_all_confirm]
)