rameshmoorthy commited on
Commit
94fc39d
·
verified ·
1 Parent(s): fdb9584

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -31
app.py CHANGED
@@ -148,7 +148,7 @@ with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
148
 
149
  # --- Login UI (visible initially) ---
150
  with gr.Column(visible=True) as login_ui:
151
- gr.Markdown("# Audit Officer Login")
152
  gr.Markdown("Please enter the credentials to access the tool.")
153
  with gr.Row():
154
  username_input = gr.Textbox(label="Username", placeholder="Enter your username")
@@ -161,7 +161,7 @@ with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
161
  gr.Markdown("# DAR Draft Audit Report Harmonisation Tool")
162
  gr.Markdown("## Initiative by Mumbai Audit 1 Commissionerate")
163
  gr.Markdown(
164
- "Upload a Observation letter to Taxpayer or Departmental Audit Report (DAR) in PDF format. The tool will process it and generate harmonised titles for Audit paras in accordance with GST law."
165
  )
166
  request_count_output = gr.Textbox(label="Requests Made Today", interactive=False, value="Requests today: 0/400")
167
  with gr.Row():
@@ -216,16 +216,61 @@ with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
216
  )
217
 
218
  if __name__ == "__main__":
219
- demo.launch(debug=True)
220
  # import pandas as pd
221
  # from io import BytesIO
222
  # import os
223
-
224
- # # These imports assume the other python files (dar_processor.py, etc.) are in the same directory.
 
 
225
  # from dar_processor import preprocess_pdf_text
226
  # from gemini_utils import get_structured_data_with_gemini, get_harmonised_titles
227
  # from models import ParsedDARReport, HarmonisedPara
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  # def create_html_report(results_with_harmonised: list[dict]) -> str:
230
  # """Generates an HTML string to display the results in a styled table."""
231
  # if not results_with_harmonised:
@@ -255,31 +300,36 @@ if __name__ == "__main__":
255
 
256
  # def process_dar_pdf(pdf_file):
257
  # """The main processing function, called after successful login."""
 
 
 
 
 
258
  # gemini_api_key = os.environ.get("GEMINI_API_KEY")
259
  # if not pdf_file:
260
- # return "Please upload a PDF file.", None, None
261
  # if not gemini_api_key:
262
- # return "Error: GEMINI_API_KEY secret not found in Space settings.", None, None
263
 
264
  # # Step 1: Process PDF to text
265
  # full_text = preprocess_pdf_text(pdf_file.name)
266
  # if full_text.startswith("Error"):
267
- # return f"Failed to process PDF: {full_text}", None, None
268
 
269
  # # Step 2: Extract structured data
270
  # parsed_report = get_structured_data_with_gemini(gemini_api_key, full_text)
271
  # if parsed_report.parsing_errors or not parsed_report.audit_paras:
272
  # error_msg = parsed_report.parsing_errors or "Could not find any audit paras."
273
- # return error_msg, None, None
274
 
275
  # # Step 3: Get harmonised titles
276
  # original_headings = [p.audit_para_heading for p in parsed_report.audit_paras if p.audit_para_heading]
277
  # if not original_headings:
278
- # return "Found paras but no headings to harmonise.", None, None
279
-
280
  # harmonised_results = get_harmonised_titles(gemini_api_key, full_text, original_headings)
281
  # if not harmonised_results:
282
- # return "Failed to generate harmonised titles.", None, None
283
 
284
  # # Step 4: Combine and prepare outputs
285
  # harmonised_map = {item.original_heading: item.harmonised_heading for item in harmonised_results}
@@ -288,28 +338,28 @@ if __name__ == "__main__":
288
  # combined_info = (parsed_report.header.dict() if parsed_report.header else {}) | para.dict()
289
  # combined_info['harmonised_audit_para_heading'] = harmonised_map.get(para.audit_para_heading, "N/A")
290
  # final_data_list.append(combined_info)
291
-
292
  # html_output = create_html_report(final_data_list)
293
-
294
  # # Step 5: Create Excel file for download
295
  # df = pd.DataFrame(final_data_list)
296
  # excel_columns = [
297
- # 'gstin', 'trade_name', 'category', 'audit_group_number', 'audit_para_number',
298
- # 'audit_para_heading', 'harmonised_audit_para_heading', 'revenue_involved_lakhs_rs',
299
- # 'revenue_recovered_lakhs_rs', 'status_of_para', 'total_amount_detected_overall_rs',
300
  # 'total_amount_recovered_overall_rs'
301
  # ]
302
  # df = df.reindex(columns=excel_columns).fillna('N/A')
303
-
304
  # output_excel = BytesIO()
305
  # df.to_excel(output_excel, index=False, sheet_name='DAR_Extraction')
306
  # output_excel.seek(0)
307
-
308
  # excel_file_name = "dar_extraction_report.xlsx"
309
  # with open(excel_file_name, "wb") as f:
310
  # f.write(output_excel.getbuffer())
311
 
312
- # return "Processing complete.", html_output, gr.File(value=excel_file_name)
313
 
314
  # # --- Gradio Interface Definition ---
315
  # with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
@@ -329,9 +379,9 @@ if __name__ == "__main__":
329
  # gr.Markdown("# DAR Draft Audit Report Harmonisation Tool")
330
  # gr.Markdown("## Initiative by Mumbai Audit 1 Commissionerate")
331
  # gr.Markdown(
332
- # "Upload a Observation letter to taxpayer or Departmental Audit Report (DAR) in PDF format. The tool will process it and generate harmonised titles for Audit paras in accordance with GST law."
333
-
334
  # )
 
335
  # with gr.Row():
336
  # with gr.Column(scale=1):
337
  # pdf_input = gr.File(label="Upload DAR PDF", file_types=[".pdf"])
@@ -345,7 +395,7 @@ if __name__ == "__main__":
345
  # submit_btn.click(
346
  # fn=process_dar_pdf,
347
  # inputs=[pdf_input],
348
- # outputs=[status_output, html_output, excel_output]
349
  # )
350
 
351
  # # --- Login Functionality ---
@@ -354,33 +404,201 @@ if __name__ == "__main__":
354
  # Checks user credentials against secrets.
355
  # For production, these are loaded from Hugging Face secrets.
356
  # """
357
- # # Get credentials from Hugging Face secrets.
358
- # # Fallback to default values for local testing if secrets are not set.
359
  # auth_username = os.environ.get("APP_USERNAME")
360
  # auth_password = os.environ.get("APP_PASSWORD")
361
-
362
  # is_valid_user = (username == auth_username and password == auth_password)
363
-
364
  # if is_valid_user:
365
- # # Login successful: hide login UI, show main app
 
366
  # return {
367
  # login_ui: gr.update(visible=False),
368
  # main_app_ui: gr.update(visible=True),
369
- # login_error_msg: gr.update(visible=False)
 
370
  # }
371
  # else:
372
  # # Login failed: keep login UI visible, show error message
373
  # return {
374
  # login_ui: gr.update(visible=True),
375
  # main_app_ui: gr.update(visible=False),
376
- # login_error_msg: gr.update(value="<p style='color:red;'>Invalid username or password.</p>", visible=True)
 
377
  # }
378
 
379
  # login_button.click(
380
  # login,
381
  # inputs=[username_input, password_input],
382
- # outputs=[login_ui, main_app_ui, login_error_msg]
383
  # )
384
 
385
  # if __name__ == "__main__":
386
  # demo.launch(debug=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  # --- Login UI (visible initially) ---
150
  with gr.Column(visible=True) as login_ui:
151
+ gr.Markdown("# DAR Harmonisation Tool Login")
152
  gr.Markdown("Please enter the credentials to access the tool.")
153
  with gr.Row():
154
  username_input = gr.Textbox(label="Username", placeholder="Enter your username")
 
161
  gr.Markdown("# DAR Draft Audit Report Harmonisation Tool")
162
  gr.Markdown("## Initiative by Mumbai Audit 1 Commissionerate")
163
  gr.Markdown(
164
+ "Upload a Departmental Audit Report (DAR) in PDF format. The tool will process it and generate harmonised titles for Audit paras in accordance with GST law."
165
  )
166
  request_count_output = gr.Textbox(label="Requests Made Today", interactive=False, value="Requests today: 0/400")
167
  with gr.Row():
 
216
  )
217
 
218
  if __name__ == "__main__":
219
+ demo.launch(debug=True)# import gradio as gr
220
  # import pandas as pd
221
  # from io import BytesIO
222
  # import os
223
+ # import json
224
+ # from datetime import datetime
225
+ # import firebase_admin
226
+ # from firebase_admin import credentials, firestore
227
  # from dar_processor import preprocess_pdf_text
228
  # from gemini_utils import get_structured_data_with_gemini, get_harmonised_titles
229
  # from models import ParsedDARReport, HarmonisedPara
230
 
231
+ # # Firebase setup
232
+ # FIREBASE_CREDENTIALS = os.environ.get("FIREBASE_CREDENTIALS")
233
+ # if FIREBASE_CREDENTIALS:
234
+ # # Load credentials from environment variable (preferred for security)
235
+ # cred = credentials.Certificate(json.loads(FIREBASE_CREDENTIALS))
236
+ # else:
237
+ # # Fallback to reading from firebase.json file
238
+ # if not os.path.exists("firebase.json"):
239
+ # raise ValueError("firebase.json not found and FIREBASE_CREDENTIALS not set.")
240
+ # cred = credentials.Certificate("firebase.json")
241
+
242
+ # firebase_admin.initialize_app(cred)
243
+ # db = firestore.client()
244
+ # request_counts = db.collection('request_counts')
245
+
246
+ # def get_request_count():
247
+ # """Retrieve the current request count for today."""
248
+ # today = datetime.utcnow().strftime('%Y-%m-%d')
249
+ # doc_ref = request_counts.document(today)
250
+ # doc = doc_ref.get()
251
+ # count = doc.to_dict().get('count', 0) if doc.exists else 0
252
+ # return count
253
+
254
+ # def check_request_limit():
255
+ # """Check if the request limit for the day has been reached."""
256
+ # today = datetime.utcnow().strftime('%Y-%m-%d')
257
+ # doc_ref = request_counts.document(today)
258
+ # doc = doc_ref.get()
259
+
260
+ # if not doc.exists:
261
+ # # Initialize counter for the new day
262
+ # doc_ref.set({'count': 0})
263
+ # count = 0
264
+ # else:
265
+ # count = doc.to_dict().get('count', 0)
266
+
267
+ # if count >= 400:
268
+ # return False, "Daily request limit of 400 reached. Try again tomorrow."
269
+
270
+ # # Increment the counter
271
+ # doc_ref.update({'count': firestore.Increment(1)})
272
+ # return True, None
273
+
274
  # def create_html_report(results_with_harmonised: list[dict]) -> str:
275
  # """Generates an HTML string to display the results in a styled table."""
276
  # if not results_with_harmonised:
 
300
 
301
  # def process_dar_pdf(pdf_file):
302
  # """The main processing function, called after successful login."""
303
+ # # Check request limit before processing
304
+ # can_process, error_msg = check_request_limit()
305
+ # if not can_process:
306
+ # return error_msg, None, None, f"Requests today: {get_request_count()}/400"
307
+
308
  # gemini_api_key = os.environ.get("GEMINI_API_KEY")
309
  # if not pdf_file:
310
+ # return "Please upload a PDF file.", None, None, f"Requests today: {get_request_count()}/400"
311
  # if not gemini_api_key:
312
+ # return "Error: GEMINI_API_KEY secret not found in Space settings.", None, None, f"Requests today: {get_request_count()}/400"
313
 
314
  # # Step 1: Process PDF to text
315
  # full_text = preprocess_pdf_text(pdf_file.name)
316
  # if full_text.startswith("Error"):
317
+ # return f"Failed to process PDF: {full_text}", None, None, f"Requests today: {get_request_count()}/400"
318
 
319
  # # Step 2: Extract structured data
320
  # parsed_report = get_structured_data_with_gemini(gemini_api_key, full_text)
321
  # if parsed_report.parsing_errors or not parsed_report.audit_paras:
322
  # error_msg = parsed_report.parsing_errors or "Could not find any audit paras."
323
+ # return error_msg, None, None, f"Requests today: {get_request_count()}/400"
324
 
325
  # # Step 3: Get harmonised titles
326
  # original_headings = [p.audit_para_heading for p in parsed_report.audit_paras if p.audit_para_heading]
327
  # if not original_headings:
328
+ # return "Found paras but no headings to harmonise.", None, None, f"Requests today: {get_request_count()}/400"
329
+
330
  # harmonised_results = get_harmonised_titles(gemini_api_key, full_text, original_headings)
331
  # if not harmonised_results:
332
+ # return "Failed to generate harmonised titles.", None, None, f"Requests today: {get_request_count()}/400"
333
 
334
  # # Step 4: Combine and prepare outputs
335
  # harmonised_map = {item.original_heading: item.harmonised_heading for item in harmonised_results}
 
338
  # combined_info = (parsed_report.header.dict() if parsed_report.header else {}) | para.dict()
339
  # combined_info['harmonised_audit_para_heading'] = harmonised_map.get(para.audit_para_heading, "N/A")
340
  # final_data_list.append(combined_info)
341
+
342
  # html_output = create_html_report(final_data_list)
343
+
344
  # # Step 5: Create Excel file for download
345
  # df = pd.DataFrame(final_data_list)
346
  # excel_columns = [
347
+ # 'gstin', 'trade_name', 'category', 'audit_group_number', 'audit_para_number',
348
+ # 'audit_para_heading', 'harmonised_audit_para_heading', 'revenue_involved_lakhs_rs',
349
+ # 'revenue_recovered_lakhs_rs', 'status_of_para', 'total_amount_detected_overall_rs',
350
  # 'total_amount_recovered_overall_rs'
351
  # ]
352
  # df = df.reindex(columns=excel_columns).fillna('N/A')
353
+
354
  # output_excel = BytesIO()
355
  # df.to_excel(output_excel, index=False, sheet_name='DAR_Extraction')
356
  # output_excel.seek(0)
357
+
358
  # excel_file_name = "dar_extraction_report.xlsx"
359
  # with open(excel_file_name, "wb") as f:
360
  # f.write(output_excel.getbuffer())
361
 
362
+ # return "Processing complete.", html_output, gr.File(value=excel_file_name), f"Requests today: {get_request_count()}/400"
363
 
364
  # # --- Gradio Interface Definition ---
365
  # with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
 
379
  # gr.Markdown("# DAR Draft Audit Report Harmonisation Tool")
380
  # gr.Markdown("## Initiative by Mumbai Audit 1 Commissionerate")
381
  # gr.Markdown(
382
+ # "Upload a Observation letter to Taxpayer or Departmental Audit Report (DAR) in PDF format. The tool will process it and generate harmonised titles for Audit paras in accordance with GST law."
 
383
  # )
384
+ # request_count_output = gr.Textbox(label="Requests Made Today", interactive=False, value="Requests today: 0/400")
385
  # with gr.Row():
386
  # with gr.Column(scale=1):
387
  # pdf_input = gr.File(label="Upload DAR PDF", file_types=[".pdf"])
 
395
  # submit_btn.click(
396
  # fn=process_dar_pdf,
397
  # inputs=[pdf_input],
398
+ # outputs=[status_output, html_output, excel_output, request_count_output]
399
  # )
400
 
401
  # # --- Login Functionality ---
 
404
  # Checks user credentials against secrets.
405
  # For production, these are loaded from Hugging Face secrets.
406
  # """
 
 
407
  # auth_username = os.environ.get("APP_USERNAME")
408
  # auth_password = os.environ.get("APP_PASSWORD")
409
+
410
  # is_valid_user = (username == auth_username and password == auth_password)
411
+
412
  # if is_valid_user:
413
+ # # Login successful: hide login UI, show main app, display request count
414
+ # request_count = get_request_count()
415
  # return {
416
  # login_ui: gr.update(visible=False),
417
  # main_app_ui: gr.update(visible=True),
418
+ # login_error_msg: gr.update(visible=False),
419
+ # request_count_output: gr.update(value=f"Requests today: {request_count}/400")
420
  # }
421
  # else:
422
  # # Login failed: keep login UI visible, show error message
423
  # return {
424
  # login_ui: gr.update(visible=True),
425
  # main_app_ui: gr.update(visible=False),
426
+ # login_error_msg: gr.update(value="<p style='color:red;'>Invalid username or password.</p>", visible=True),
427
+ # request_count_output: gr.update(value="Requests today: 0/400")
428
  # }
429
 
430
  # login_button.click(
431
  # login,
432
  # inputs=[username_input, password_input],
433
+ # outputs=[login_ui, main_app_ui, login_error_msg, request_count_output]
434
  # )
435
 
436
  # if __name__ == "__main__":
437
  # demo.launch(debug=True)
438
+ # # import pandas as pd
439
+ # # from io import BytesIO
440
+ # # import os
441
+
442
+ # # # These imports assume the other python files (dar_processor.py, etc.) are in the same directory.
443
+ # # from dar_processor import preprocess_pdf_text
444
+ # # from gemini_utils import get_structured_data_with_gemini, get_harmonised_titles
445
+ # # from models import ParsedDARReport, HarmonisedPara
446
+
447
+ # # def create_html_report(results_with_harmonised: list[dict]) -> str:
448
+ # # """Generates an HTML string to display the results in a styled table."""
449
+ # # if not results_with_harmonised:
450
+ # # return "<p>No audit paras found or processed.</p>"
451
+ # # style = """
452
+ # # <style>
453
+ # # body { font-family: sans-serif; }
454
+ # # .styled-table {
455
+ # # border-collapse: collapse; margin: 25px 0; font-size: 0.9em;
456
+ # # min-width: 400px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
457
+ # # border-radius: 8px; overflow: hidden;
458
+ # # }
459
+ # # .styled-table thead tr { background-color: #009879; color: #ffffff; text-align: left; }
460
+ # # .styled-table th, .styled-table td { padding: 12px 15px; border-bottom: 1px solid #dddddd; }
461
+ # # .styled-table tbody tr:last-of-type { border-bottom: 2px solid #009879; }
462
+ # # </style>
463
+ # # """
464
+ # # html = f"{style}<table class='styled-table'><thead><tr><th>Para No.</th><th>Original Audit Para Heading</th><th>Harmonised Audit Para Heading</th><th>Amount Involved (in Lakhs)</th></tr></thead><tbody>"
465
+ # # for item in results_with_harmonised:
466
+ # # para_num = item.get('audit_para_number', 'N/A')
467
+ # # original_heading = item.get('audit_para_heading', 'N/A')
468
+ # # harmonised_heading = item.get('harmonised_audit_para_heading', 'N/A')
469
+ # # amount = f"₹{item.get('revenue_involved_lakhs_rs', 0.0):,.2f} L"
470
+ # # html += f"<tr><td>{para_num}</td><td>{original_heading}</td><td>{harmonised_heading}</td><td>{amount}</td></tr>"
471
+ # # html += "</tbody></table>"
472
+ # # return html
473
+
474
+ # # def process_dar_pdf(pdf_file):
475
+ # # """The main processing function, called after successful login."""
476
+ # # gemini_api_key = os.environ.get("GEMINI_API_KEY")
477
+ # # if not pdf_file:
478
+ # # return "Please upload a PDF file.", None, None
479
+ # # if not gemini_api_key:
480
+ # # return "Error: GEMINI_API_KEY secret not found in Space settings.", None, None
481
+
482
+ # # # Step 1: Process PDF to text
483
+ # # full_text = preprocess_pdf_text(pdf_file.name)
484
+ # # if full_text.startswith("Error"):
485
+ # # return f"Failed to process PDF: {full_text}", None, None
486
+
487
+ # # # Step 2: Extract structured data
488
+ # # parsed_report = get_structured_data_with_gemini(gemini_api_key, full_text)
489
+ # # if parsed_report.parsing_errors or not parsed_report.audit_paras:
490
+ # # error_msg = parsed_report.parsing_errors or "Could not find any audit paras."
491
+ # # return error_msg, None, None
492
+
493
+ # # # Step 3: Get harmonised titles
494
+ # # original_headings = [p.audit_para_heading for p in parsed_report.audit_paras if p.audit_para_heading]
495
+ # # if not original_headings:
496
+ # # return "Found paras but no headings to harmonise.", None, None
497
+
498
+ # # harmonised_results = get_harmonised_titles(gemini_api_key, full_text, original_headings)
499
+ # # if not harmonised_results:
500
+ # # return "Failed to generate harmonised titles.", None, None
501
+
502
+ # # # Step 4: Combine and prepare outputs
503
+ # # harmonised_map = {item.original_heading: item.harmonised_heading for item in harmonised_results}
504
+ # # final_data_list = []
505
+ # # for para in parsed_report.audit_paras:
506
+ # # combined_info = (parsed_report.header.dict() if parsed_report.header else {}) | para.dict()
507
+ # # combined_info['harmonised_audit_para_heading'] = harmonised_map.get(para.audit_para_heading, "N/A")
508
+ # # final_data_list.append(combined_info)
509
+
510
+ # # html_output = create_html_report(final_data_list)
511
+
512
+ # # # Step 5: Create Excel file for download
513
+ # # df = pd.DataFrame(final_data_list)
514
+ # # excel_columns = [
515
+ # # 'gstin', 'trade_name', 'category', 'audit_group_number', 'audit_para_number',
516
+ # # 'audit_para_heading', 'harmonised_audit_para_heading', 'revenue_involved_lakhs_rs',
517
+ # # 'revenue_recovered_lakhs_rs', 'status_of_para', 'total_amount_detected_overall_rs',
518
+ # # 'total_amount_recovered_overall_rs'
519
+ # # ]
520
+ # # df = df.reindex(columns=excel_columns).fillna('N/A')
521
+
522
+ # # output_excel = BytesIO()
523
+ # # df.to_excel(output_excel, index=False, sheet_name='DAR_Extraction')
524
+ # # output_excel.seek(0)
525
+
526
+ # # excel_file_name = "dar_extraction_report.xlsx"
527
+ # # with open(excel_file_name, "wb") as f:
528
+ # # f.write(output_excel.getbuffer())
529
+
530
+ # # return "Processing complete.", html_output, gr.File(value=excel_file_name)
531
+
532
+ # # # --- Gradio Interface Definition ---
533
+ # # with gr.Blocks(theme=gr.themes.Soft(), title="DAR Harmonisation Tool") as demo:
534
+
535
+ # # # --- Login UI (visible initially) ---
536
+ # # with gr.Column(visible=True) as login_ui:
537
+ # # gr.Markdown("# Audit Officer Login")
538
+ # # gr.Markdown("Please enter the credentials to access the tool.")
539
+ # # with gr.Row():
540
+ # # username_input = gr.Textbox(label="Username", placeholder="Enter your username")
541
+ # # password_input = gr.Textbox(label="Password", type="password", placeholder="Enter your password")
542
+ # # login_button = gr.Button("Login", variant="primary")
543
+ # # login_error_msg = gr.Markdown(visible=False)
544
+
545
+ # # # --- Main App UI (hidden initially) ---
546
+ # # with gr.Column(visible=False) as main_app_ui:
547
+ # # gr.Markdown("# DAR Draft Audit Report Harmonisation Tool")
548
+ # # gr.Markdown("## Initiative by Mumbai Audit 1 Commissionerate")
549
+ # # gr.Markdown(
550
+ # # "Upload a Observation letter to taxpayer or Departmental Audit Report (DAR) in PDF format. The tool will process it and generate harmonised titles for Audit paras in accordance with GST law."
551
+
552
+ # # )
553
+ # # with gr.Row():
554
+ # # with gr.Column(scale=1):
555
+ # # pdf_input = gr.File(label="Upload DAR PDF", file_types=[".pdf"])
556
+ # # submit_btn = gr.Button("Process Report", variant="primary")
557
+ # # with gr.Column(scale=2):
558
+ # # status_output = gr.Textbox(label="Processing Status", interactive=False)
559
+ # # excel_output = gr.File(label="Download Excel Report")
560
+ # # gr.Markdown("## Harmonised Audit Para Titles")
561
+ # # html_output = gr.HTML()
562
+
563
+ # # submit_btn.click(
564
+ # # fn=process_dar_pdf,
565
+ # # inputs=[pdf_input],
566
+ # # outputs=[status_output, html_output, excel_output]
567
+ # # )
568
+
569
+ # # # --- Login Functionality ---
570
+ # # def login(username, password):
571
+ # # """
572
+ # # Checks user credentials against secrets.
573
+ # # For production, these are loaded from Hugging Face secrets.
574
+ # # """
575
+ # # # Get credentials from Hugging Face secrets.
576
+ # # # Fallback to default values for local testing if secrets are not set.
577
+ # # auth_username = os.environ.get("APP_USERNAME")
578
+ # # auth_password = os.environ.get("APP_PASSWORD")
579
+
580
+ # # is_valid_user = (username == auth_username and password == auth_password)
581
+
582
+ # # if is_valid_user:
583
+ # # # Login successful: hide login UI, show main app
584
+ # # return {
585
+ # # login_ui: gr.update(visible=False),
586
+ # # main_app_ui: gr.update(visible=True),
587
+ # # login_error_msg: gr.update(visible=False)
588
+ # # }
589
+ # # else:
590
+ # # # Login failed: keep login UI visible, show error message
591
+ # # return {
592
+ # # login_ui: gr.update(visible=True),
593
+ # # main_app_ui: gr.update(visible=False),
594
+ # # login_error_msg: gr.update(value="<p style='color:red;'>Invalid username or password.</p>", visible=True)
595
+ # # }
596
+
597
+ # # login_button.click(
598
+ # # login,
599
+ # # inputs=[username_input, password_input],
600
+ # # outputs=[login_ui, main_app_ui, login_error_msg]
601
+ # # )
602
+
603
+ # # if __name__ == "__main__":
604
+ # # demo.launch(debug=True)