report / src /streamlit_app.py
digitalai's picture
Update src/streamlit_app.py
48de452 verified
import streamlit as st
import pandas as pd
import re
import plotly.express as px
st.set_page_config(page_title="گزارش خرید کالا و داشبورد تصویری", layout="wide", initial_sidebar_state="expanded")
# --- بارگذاری فونت Vazirmatn از CDN ---
st.markdown(
"""
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-Variable-font-face.css" rel="stylesheet" type="text/css" />
""",
unsafe_allow_html=True
)
# --- بارگذاری فایل CSS ---
with open("src/style.css") as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
st.title("📊 گزارش خرید کالا و داشبورد تصویری")
# --- سایدبار ---
with st.sidebar:
st.header("تنظیمات")
uploaded_file = st.file_uploader("📂 فایل اکسل Book.xlsx را بارگذاری کنید", type=["xlsx"])
if uploaded_file is not None:
df = pd.read_excel(uploaded_file)
# --- تمیزکاری ستون‌ها ---
def clean_col(col):
col = str(col)
col = re.sub(r'[\n\r]+', ' ', col)
col = re.sub(r'[\u200c\u200f\u202a-\u202e\ufeff]', '', col)
col = re.sub(r'\s+', ' ', col).strip()
return col
df.columns = [clean_col(c) for c in df.columns]
# --- پیدا کردن ستون تعداد و مبلغ ---
qty_col = next((c for c in df.columns if re.search(r'خالص.*تعداد', c)), None)
amt_col = next((c for c in df.columns if re.search(r'خالص.*مبلغ(?!.*تخفیف)', c)), None)
if not qty_col or not amt_col:
st.error("❌ ستون‌های مربوط به «خالص تعداد» یا «خالص مبلغ» پیدا نشدند!")
st.write("📑 ستون‌های موجود در فایل (بعد از تمیزکاری):")
st.write(list(df.columns))
else:
# اطمینان از اینکه ستون مبلغ عددی است و NaN ندارد
df[amt_col] = pd.to_numeric(df[amt_col], errors='coerce').fillna(0)
# --- نگاشت ماه‌ها ---
month_order = ['فروردین','اردیبهشت','خرداد','تیر','مرداد','شهریور',
'مهر','آبان','آذر','دی','بهمن','اسفند']
month_dict = {
"01": "فروردین", "02": "اردیبهشت", "03": "خرداد", "04": "تیر",
"05": "مرداد", "06": "شهریور", "07": "مهر", "08": "آبان",
"09": "آذر", "10": "دی", "11": "بهمن", "12": "اسفند"
}
df['کدماه'] = df['نام ماه'].astype(str).str[:2]
df['ماه'] = df['کدماه'].map(month_dict)
# --- Pivot مشتری ---
grouped = df.groupby(['کد کالا','نام کالا','طرف حساب','ماه']).agg({
qty_col:'sum', amt_col:'sum'
}).reset_index()
pivot_qty = grouped.pivot_table(
index=['کد کالا','نام کالا','طرف حساب'],
columns='ماه', values=qty_col, fill_value=0
).reindex(columns=month_order, fill_value=0)
total_amount = grouped.groupby(['کد کالا','نام کالا','طرف حساب'])[amt_col].sum()
pivot_qty['مجموع مبلغ خرید'] = total_amount
report_customer = pivot_qty.reset_index()
tab1, tab2, tab3, tab4 = st.tabs(["گزارش مشتری", "گزارش تجمیعی تعداد", "گزارش تجمیعی مبلغ", "داشبورد تصویری"])
with tab1:
st.subheader("📋 گزارش خرید هر شخص برای هر کالا")
st.dataframe(report_customer, use_container_width=True)
st.download_button("⬇️ دانلود گزارش مشتری (CSV)", report_customer.to_csv(index=False, encoding='utf-8-sig'),
"Sales_Report_ByCustomer.csv", "text/csv", use_container_width=True)
# --- Pivot تجمیعی ---
grouped_total = df.groupby(['کد کالا','نام کالا','ماه']).agg({qty_col:'sum', amt_col:'sum'}).reset_index()
pivot_qty_total = grouped_total.pivot_table(
index=['کد کالا','نام کالا'], columns='ماه', values=qty_col, fill_value=0
).reindex(columns=month_order, fill_value=0)
pivot_amt_total = grouped_total.pivot_table(
index=['کد کالا','نام کالا'], columns='ماه', values=amt_col, fill_value=0
).reindex(columns=month_order, fill_value=0)
# جمع کل
pivot_qty_total['جمع کل تعداد'] = pivot_qty_total.sum(axis=1)
pivot_amt_total['جمع کل مبلغ'] = pivot_amt_total.sum(axis=1)
with tab2:
st.subheader("📦 گزارش تجمیعی تعداد فروش کل کالاها")
st.dataframe(pivot_qty_total.reset_index(), use_container_width=True)
st.download_button("⬇️ دانلود گزارش تجمیعی تعداد (CSV)", pivot_qty_total.reset_index().to_csv(index=False, encoding='utf-8-sig'),
"Total_Quantity_Report.csv", "text/csv", use_container_width=True)
with tab3:
st.subheader("💰 گزارش تجمیعی مبلغ فروش کل کالاها")
st.dataframe(pivot_amt_total.reset_index(), use_container_width=True)
st.download_button("⬇️ دانلود گزارش تجمیعی مبلغ (CSV)", pivot_amt_total.reset_index().to_csv(index=False, encoding='utf-8-sig'),
"Total_Amount_Report.csv", "text/csv", use_container_width=True)
with tab4:
st.header("📊 نمودارهای فروش")
# --- Top مشتری‌ها ---
sales_by_customer = df.groupby('طرف حساب')[amt_col].sum().sort_values(ascending=False).head(10).reset_index()
sales_by_customer.columns = ['طرف حساب', 'مبلغ فروش']
fig1 = px.bar(sales_by_customer, x='طرف حساب', y='مبلغ فروش', title="🏆 برترین مشتری‌ها", color='مبلغ فروش')
st.plotly_chart(fig1, use_container_width=True)
# --- Top کالاها ---
sales_by_product = df.groupby('نام کالا')[amt_col].sum().sort_values(ascending=False).head(10).reset_index()
sales_by_product.columns = ['نام کالا', 'مبلغ فروش']
fig2 = px.bar(sales_by_product, x='نام کالا', y='مبلغ فروش', title="📦 برترین کالاها", color='مبلغ فروش')
st.plotly_chart(fig2, use_container_width=True)
# 3. فروش ماهانه
sales_by_month = df.groupby('ماه')[amt_col].sum().reindex(month_order, fill_value=0)
fig3 = px.bar(x=sales_by_month.index, y=sales_by_month.values, title="📅 فروش ماهانه", labels={'y':'مبلغ فروش', 'x':'ماه'})
st.plotly_chart(fig3, use_container_width=True)
# 4. سهم مشتری‌ها
top_5_customers = sales_by_customer.head(5)
fig4 = px.pie(top_5_customers, values='مبلغ فروش',
names='طرف حساب', title="🥧 سهم مشتری‌ها از کل فروش (Top 5)")
st.plotly_chart(fig4, use_container_width=True)
# 5. سهم کالاها
top_5_products = sales_by_product.head(5)
fig5 = px.pie(top_5_products, values='مبلغ فروش',
names='نام کالا', title="🥧 سهم کالاها از کل فروش (Top 5)")
st.plotly_chart(fig5, use_container_width=True)
# 6. Trend فروش ماهانه
fig6 = px.line(sales_by_month, title="📈 روند فروش در طول سال", labels={'value':'مبلغ فروش', 'index':'ماه'}, markers=True)
st.plotly_chart(fig6, use_container_width=True)