Spaces:
Sleeping
Sleeping
import os | |
import pandas as pd | |
import streamlit as st | |
from google.cloud import bigquery | |
from utils import load_gcp_credentials, authenticate_bigquery_updated | |
from html_templates import logo, payment_title, progress_bar_style, process_file_title, process_date_title, button_styles, download_button_styles, tooltip_message_payment, update_sett_placeholder,update_sett_title, conso_date_title | |
import io | |
import zipfile | |
from datetime import datetime | |
import time | |
from payment_queries import queries | |
from streamlit_option_menu import option_menu | |
from merge_queries import queries_merged_01, queries_merged_02, queries_merged_03, conso_query, disburse_query | |
from io import BytesIO | |
# ---- πΉ Inject Custom CSS for Styling ---- | |
st.markdown(progress_bar_style,unsafe_allow_html=True) | |
# ---- πΉ Streamlit UI ---- | |
st.markdown(logo, unsafe_allow_html=True) | |
st.logo("alerter_4.jpeg") | |
st.markdown(payment_title, unsafe_allow_html=True) | |
st.write("") | |
st.markdown(tooltip_message_payment, unsafe_allow_html = True) | |
st.write("") | |
selected = option_menu( | |
menu_title=None, | |
options=["Payment File", "Disbursement File"], | |
icons=["database", "bar-chart"], | |
menu_icon="cast", | |
default_index=0, | |
orientation="horizontal", | |
styles={ | |
"container": { | |
"padding": "0px", | |
"background-color": "#800000 !important" # Maroon with force override | |
}, | |
"icon": { | |
"color": "#ffffff !important", # White icons with forced override | |
"font-size": "20px" | |
}, | |
"nav-link": { | |
"font-size": "18px", | |
"text-align": "center", | |
"margin": "0px", | |
"padding": "10px", | |
"color": "#ffffff !important", # White text for unselected tabs | |
"background-color": "#800000 !important", # Force maroon | |
}, | |
"nav-link-selected": { | |
"background-color": "#a52a2a !important", # Reddish maroon for selected tab | |
"color": "#ffffff !important", # White text for selected tab | |
"font-weight": "bold", | |
}, | |
}, | |
) | |
# ---- πΉ User Input Date ---- | |
if selected == 'Payment File': | |
st.markdown(process_date_title, unsafe_allow_html = True) | |
st.write("") | |
selected_date = st.date_input("", value=datetime.today()) # Default: Today | |
formatted_date = selected_date.strftime("%Y-%m-%d") # Convert to string format YYYY-MM-DD | |
# ---- πΉ Run Queries Button ---- | |
st.markdown(button_styles, unsafe_allow_html = True) | |
if st.button("Generate Payment File"): | |
st.markdown(process_file_title, unsafe_allow_html = True) | |
st.write("") | |
st.write("") | |
# Define sheet names | |
sheet_names = [ | |
"09", "11", "12", "MD", "Not_match_09", "Not_match_11", "Not_match_12" | |
] | |
# Retrieve the service account credentials | |
gcp_credentials = load_gcp_credentials() | |
if gcp_credentials: | |
bigquery_creds = authenticate_bigquery_updated() | |
client = bigquery.Client(credentials=bigquery_creds) | |
# Store DataFrames | |
dataframes = {} | |
# ---- π **Dynamic Log Section** ---- | |
log_area = st.empty() | |
log_text_list = [] # Store logs as a list | |
# ---- π **Progress Bar Setup** ---- | |
progress_bar = st.progress(0) # Initialize progress bar | |
progress_text = st.empty() # Placeholder for text | |
total_steps = len(queries) # Total number of queries to process | |
for i, (query_name, query) in enumerate(queries.items()): | |
sheet_name = sheet_names[i] if i < len(sheet_names) else f"Sheet_{i+1}" | |
# πΉ **Modify Query to Include Selected Date** | |
dynamic_query = query.replace("{selected_date}", formatted_date) | |
# π **Blinking Cursor Effect** | |
cursor_state = ["|", "/", "-", "\\"] | |
for cursor in cursor_state: | |
log_text_list.append( | |
f"<p class='gradient-text'>π΅ {sheet_name} is being processed... <span class='blinking-cursor'>{cursor}</span></p>" | |
) | |
log_area.markdown("".join(log_text_list), unsafe_allow_html=True) # β FORCE NEWLINES | |
log_text_list.pop() # Remove last blinking message to replace it | |
time.sleep(0.3) | |
try: | |
# Execute Query | |
query_job = client.query(dynamic_query) | |
df = query_job.to_dataframe() | |
# πΉ **Fix: Remove Timezone from Datetime Columns** | |
for col in df.select_dtypes(include=["datetime64[ns, UTC]"]).columns: | |
df[col] = df[col].dt.tz_localize(None) | |
# Store the DataFrame | |
dataframes[sheet_name] = df | |
# π **Static Log with Record Count** | |
record_count = len(df) | |
log_text_list.append( | |
f"<p class='gradient-text'>β {sheet_name} sheet created successfully... Total <b>{record_count}</b> records.</p>" | |
) | |
log_area.markdown("".join(log_text_list), unsafe_allow_html=True) # β FORCE NEWLINES | |
except Exception as e: | |
log_text_list.append(f"<p class='gradient-text'>β Error in {sheet_name}: {e}</p>") | |
log_area.markdown("".join(log_text_list), unsafe_allow_html=True) | |
# ---- π **Update Progress Bar (Stay at 99%)** ---- | |
progress_percentage = int(((i + 1) / total_steps) * 98) # Keep it at max 98% | |
progress_bar.progress(progress_percentage) | |
progress_text.markdown( | |
f'<p class="gradient-text">βοΈ Creating Payment File... {progress_percentage}%</p>', | |
unsafe_allow_html=True | |
) | |
time.sleep(0.5) # Small delay to simulate processing | |
# ---- π₯ Generate & Show Download Buttons (Only Now Progress Reaches 100%) ---- | |
if dataframes: | |
progress_bar.progress(99) # Keep at 99% while preparing file | |
progress_text.markdown('<p class="gradient-text">βοΈ Finalizing file... Please wait...</p>', unsafe_allow_html=True) | |
# π₯ **Excel Generation** | |
excel_buffer = io.BytesIO() | |
with pd.ExcelWriter(excel_buffer, engine="openpyxl") as writer: | |
for sheet, df in dataframes.items(): | |
df.to_excel(writer, sheet_name=sheet, index=False) | |
excel_buffer.seek(0) | |
# π₯ **CSV ZIP Generation** | |
csv_buffer = io.BytesIO() | |
with zipfile.ZipFile(csv_buffer, "w", zipfile.ZIP_DEFLATED) as zipf: | |
for sheet, df in dataframes.items(): | |
csv_data = df.to_csv(index=False).encode("utf-8") | |
zipf.writestr(f"{sheet}_{formatted_date}.csv", csv_data) | |
csv_buffer.seek(0) | |
# ---- β **Now Move Progress to 100% and Show Download Options** ---- | |
progress_bar.progress(100) | |
progress_text.markdown('<p class="gradient-text">β Payment file created. Ready for download.</p>', unsafe_allow_html=True) | |
# ---- π₯ Download Buttons ---- | |
st.markdown(download_button_styles, unsafe_allow_html = True) | |
st.download_button( | |
label=f"π₯ Download Payment File", | |
data=excel_buffer, | |
file_name=f"queries_results_{formatted_date}.xlsx", | |
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | |
) | |
elif selected == 'Disbursement File': | |
gcp_credentials = load_gcp_credentials() | |
# Radio Button for Selection | |
st.markdown(update_sett_placeholder,unsafe_allow_html=True) | |
# Styled Radio Button | |
st.markdown(update_sett_title, unsafe_allow_html = True) | |
update_option = st.radio( | |
"", | |
["Update 09", "Update 11", "Update 12"] | |
) | |
# Map selection to queries | |
if update_option == "Update 09": | |
selected_queries = queries_merged_01 | |
elif update_option == "Update 11": | |
selected_queries = queries_merged_02 | |
elif update_option == "Update 12": | |
selected_queries = queries_merged_03 | |
else: | |
selected_queries = [] | |
# Button to execute queries | |
st.markdown(button_styles, unsafe_allow_html = True) | |
if st.button("Execute Updates") and selected_queries: | |
st.markdown("<h3 style='text-align: center; color: maroon;'>Executing Queries & Updating IDs</h3>", unsafe_allow_html=True) | |
gcp_credentials = load_gcp_credentials() | |
if gcp_credentials: | |
bigquery_creds = authenticate_bigquery_updated() | |
client = bigquery.Client(credentials=bigquery_creds) | |
total_queries = len(selected_queries) | |
progress_bar = st.progress(0) | |
updated_counts = {} | |
for i, query in enumerate(selected_queries): | |
st.markdown(f"### Running Query {i+1} of {total_queries}...") | |
start_time = time.time() | |
# Execute query | |
query_job = client.query(query) | |
query_job.result() | |
updated_count = query_job.num_dml_affected_rows or 0 | |
updated_counts[f"Query {i+1}"] = updated_count | |
# Update progress bar | |
progress = int(((i + 1) / total_queries) * 100) | |
progress_bar.progress(progress / 100) | |
# Display execution details | |
execution_time = time.time() - start_time | |
st.success(f"β Query {i+1} executed in {execution_time:.2f} sec. **{updated_count} IDs updated.**") | |
time.sleep(1) | |
# Summary | |
progress_bar.progress(1.0) | |
# Streamlit Date Input | |
st.markdown(conso_date_title, unsafe_allow_html = True) | |
selected_date = st.date_input("") | |
# If a date is selected, show the download button | |
st.markdown(button_styles, unsafe_allow_html = True) | |
if st.button('Generate disbursement') and selected_date: | |
selected_date_str = selected_date.strftime("%Y-%m-%d") | |
if selected_date_str: | |
# β Authenticate with BigQuery | |
gcp_credentials = load_gcp_credentials() | |
if gcp_credentials: | |
bigquery_creds = authenticate_bigquery_updated() | |
client = bigquery.Client(credentials=bigquery_creds) | |
# β Set query parameters | |
job_config = bigquery.QueryJobConfig( | |
query_parameters=[ | |
bigquery.ScalarQueryParameter("selected_date", "DATE", selected_date_str) | |
] | |
) | |
# β Execute queries | |
conso_df = client.query(conso_query, job_config=job_config).to_dataframe() | |
disburse_df = client.query(disburse_query, job_config=job_config).to_dataframe() | |
# β Remove timezone and convert datetime columns | |
def clean_datetime_columns(df): | |
for col in df.select_dtypes(include=["datetime64[ns, UTC]"]).columns: | |
df[col] = df[col].dt.tz_localize(None) # Remove timezone | |
for col in df.select_dtypes(include=["datetime64"]).columns: | |
df[col] = df[col].astype(str) # Convert datetime to string | |
clean_datetime_columns(conso_df) | |
clean_datetime_columns(disburse_df) | |
# β Save to an in-memory Excel file | |
output = BytesIO() | |
with pd.ExcelWriter(output, engine="xlsxwriter") as writer: | |
conso_df.to_excel(writer, sheet_name="Sheet1", index=False) | |
disburse_df.to_excel(writer, sheet_name="disbursement_summary", index=False) | |
output.seek(0) # β Reset buffer position | |
# β Place buttons side by side | |
col1, col2 = st.columns(2) | |
with col1: | |
st.download_button( | |
label="Download Disbursement Data", | |
data=output, | |
file_name=f"disbursement_data_{selected_date_str}.xlsx", | |
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | |
) | |
with col2: | |
if st.button("Generate Disbursement"): | |
st.success("Disbursement Generated Successfully β ") | |