|
import streamlit as st |
|
import pandas as pd |
|
import os |
|
from datetime import datetime |
|
from PIL import Image, ImageDraw, ImageFont |
|
import io |
|
import re |
|
|
|
|
|
if 'df' not in st.session_state: |
|
st.session_state.df = None |
|
if 'selected_phone' not in st.session_state: |
|
st.session_state.selected_phone = None |
|
|
|
|
|
DATA_FILE = "./data/tailor_data.csv" |
|
BACKUP_FILE = "./data/backup.csv" |
|
EXPORT_DIR = "./exports" |
|
|
|
|
|
os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True) |
|
os.makedirs(EXPORT_DIR, exist_ok=True) |
|
|
|
|
|
FIELDS = [ |
|
"سیریل نمبر", "گاہک کا نام", "موبائل نمبر", "قمیض کی لمبائی", "شلوار کی لمبائی", |
|
"بازو", "کالر", "بین", "شلوار پاکٹ", "سائیڈ پاکٹ", "گھیرا", "پائنچہ", "پٹی", |
|
"چھاتی", "انٹری کرنے والے کا نام", "بٹن یا اضافی معلومات", "تاریخ و وقت" |
|
] |
|
MANDATORY_FIELDS = FIELDS[:14] |
|
|
|
def load_data(): |
|
"""Load data from CSV or backup, or create new DataFrame.""" |
|
columns = FIELDS |
|
if os.path.exists(DATA_FILE): |
|
try: |
|
df = pd.read_csv(DATA_FILE) |
|
if not df.empty: |
|
df['موبائل نمبر'] = df['موبائل نمبر'].astype(str) |
|
df['سیریل نمبر'] = df['سیریل نمبر'].astype(str) |
|
return df |
|
except Exception as e: |
|
st.warning(f"Error reading primary file: {e}") |
|
if os.path.exists(BACKUP_FILE): |
|
try: |
|
df = pd.read_csv(BACKUP_FILE) |
|
df['موبائل نمبر'] = df['موبائل نمبر'].astype(str) |
|
df['سیریل نمبر'] = df['سیریل نمبر'].astype(str) |
|
return df |
|
except Exception as e: |
|
st.warning(f"Error reading backup file: {e}") |
|
return pd.DataFrame(columns=columns) |
|
|
|
def save_data(df): |
|
"""Save data to CSV and append to backup.""" |
|
try: |
|
df.to_csv(DATA_FILE, index=False) |
|
except Exception as e: |
|
st.warning(f"Could not save to primary file: {e}") |
|
|
|
try: |
|
if os.path.exists(BACKUP_FILE): |
|
backup_df = pd.read_csv(BACKUP_FILE) |
|
backup_df['موبائل نمبر'] = backup_df['موبائل نمبر'].astype(str) |
|
backup_df['سیریل نمبر'] = backup_df['سیریل نمبر'].astype(str) |
|
df['موبائل نمبر'] = df['موبائل نمبر'].astype(str) |
|
df['سیریل نمبر'] = df['سیریل نمبر'].astype(str) |
|
new_records = df[~df['سیریل نمبر'].isin(backup_df['سیریل نمبر']) & |
|
~df['موبائل نمبر'].isin(backup_df['موبائل نمبر'])] |
|
if not new_records.empty: |
|
new_records.to_csv(BACKUP_FILE, mode='a', header=False, index=False) |
|
else: |
|
df.to_csv(BACKUP_FILE, index=False) |
|
except Exception as e: |
|
st.warning(f"Could not save to backup: {e}") |
|
|
|
def validate_numeric(value): |
|
"""Check if value is numeric.""" |
|
return bool(re.match(r'^\d*$', value)) |
|
|
|
def create_image_from_details(customer, filename): |
|
"""Generate an image from customer details.""" |
|
img = Image.new('RGB', (600, 800), color='white') |
|
draw = ImageDraw.Draw(img) |
|
|
|
try: |
|
font = ImageFont.truetype("arial.ttf", 20) |
|
except: |
|
font = ImageFont.load_default() |
|
|
|
y = 20 |
|
for key, value in customer.items(): |
|
if pd.notna(value): |
|
value = str(value) |
|
if key not in ["گاہک کا نام", "موبائل نمبر", "انٹری کرنے والے کا نام", "سیریل نمبر", "بٹن یا اضافی معلومات", "تاریخ و وقت"]: |
|
value = "".join(value.split()) |
|
text = f"{key}: {value}" |
|
draw.text((20, y), text, font=font, fill='black', direction='rtl') |
|
y += 40 |
|
|
|
img.save(os.path.join(EXPORT_DIR, filename)) |
|
|
|
def main(): |
|
st.title("Riwaj Tailors Wah Cantt") |
|
st.markdown("Software Developed by: Muhammad Haris [[email protected]]") |
|
|
|
|
|
st.session_state.df = load_data() |
|
|
|
|
|
tab1, tab2 = st.tabs(["Add Customer", "View/Edit Customers"]) |
|
|
|
with tab1: |
|
st.header("Add Customer") |
|
with st.form(key="add_customer_form"): |
|
data = {} |
|
cols = st.columns(2) |
|
for i, field in enumerate(FIELDS[:-1]): |
|
col = cols[i % 2] |
|
data[field] = col.text_input(f"{field}:", key=f"add_{field}") |
|
|
|
submit_button = st.form_submit_button("Save Customer") |
|
|
|
if submit_button: |
|
|
|
for field in MANDATORY_FIELDS: |
|
if not data[field].strip(): |
|
st.error(f"{field} is required!") |
|
break |
|
if field in ["سیریل نمبر", "موبائل نمبر"] and not validate_numeric(data[field]): |
|
st.error(f"{field} must be numeric!") |
|
break |
|
else: |
|
|
|
if not st.session_state.df.empty: |
|
if data["موبائل نمبر"] in st.session_state.df["موبائل نمبر"].astype(str).values: |
|
st.error("موبائل نمبر پہلے سے موجود ہے!") |
|
elif data["سیریل نمبر"] in st.session_state.df["سیریل نمبر"].astype(str).values: |
|
st.error("سیریل نمبر پہلے سے موجود ہے!") |
|
else: |
|
data["تاریخ و وقت"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
st.session_state.df = pd.concat([st.session_state.df, pd.DataFrame([data])], ignore_index=True) |
|
save_data(st.session_state.df) |
|
st.success("Customer saved successfully!") |
|
else: |
|
data["تاریخ و وقت"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
st.session_state.df = pd.DataFrame([data]) |
|
save_data(st.session_state.df) |
|
st.success("Customer saved successfully!") |
|
|
|
with tab2: |
|
st.header("View/Edit Customers") |
|
search_term = st.text_input("Search:", key="search") |
|
|
|
|
|
if search_term: |
|
filtered_df = st.session_state.df[ |
|
st.session_state.df["سیریل نمبر"].str.contains(search_term, na=False, case=False) | |
|
st.session_state.df["گاہک کا نام"].str.contains(search_term, na=False, case=False) | |
|
st.session_state.df["موبائل نمبر"].str.contains(search_term, na=False, case=False) |
|
] |
|
else: |
|
filtered_df = st.session_state.df |
|
|
|
|
|
if not filtered_df.empty: |
|
st.dataframe(filtered_df[["سیریل نمبر", "گاہک کا نام", "موبائل نمبر"]], use_container_width=True) |
|
|
|
|
|
phone_input = st.text_input("Enter Phone Number to View Details:", key="view_phone") |
|
if st.button("View Details"): |
|
if phone_input: |
|
customer_data = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) == phone_input] |
|
if not customer_data.empty: |
|
customer = customer_data.iloc[0] |
|
details = [] |
|
for key, value in customer.items(): |
|
if pd.notna(value): |
|
value = str(value) |
|
if key not in ["گاہک کا نام", "موبائل نمبر", "انٹری کرنے والے کا نام", "سیریل نمبر", "بٹن یا اضافی معلومات", "تاریخ و وقت"]: |
|
value = "".join(value.split()) |
|
details.append(f"{key}: {value}") |
|
st.write("\n".join(details)) |
|
else: |
|
st.error("Customer not found!") |
|
else: |
|
st.warning("Please enter a phone number!") |
|
|
|
|
|
with st.expander("Edit Customer"): |
|
edit_phone = st.text_input("Enter Phone Number to Edit:", key="edit_phone") |
|
if st.button("Load Customer"): |
|
if edit_phone: |
|
customer_data = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) == edit_phone] |
|
if not customer_data.empty: |
|
st.session_state.selected_phone = edit_phone |
|
st.success("Customer loaded for editing!") |
|
else: |
|
st.error("Customer not found!") |
|
else: |
|
st.warning("Please enter a phone number!") |
|
|
|
if st.session_state.selected_phone: |
|
customer_data = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) == st.session_state.selected_phone] |
|
if not customer_data.empty: |
|
customer = customer_data.iloc[0] |
|
with st.form(key="edit_customer_form"): |
|
edit_data = {} |
|
cols = st.columns(2) |
|
for i, field in enumerate(FIELDS[:-1]): |
|
col = cols[i % 2] |
|
edit_data[field] = col.text_input(f"{field}:", value=str(customer[field]), key=f"edit_{field}_{edit_phone}") |
|
submit_edit = st.form_submit_button("Save Changes") |
|
|
|
if submit_edit: |
|
for field in MANDATORY_FIELDS: |
|
if not edit_data[field].strip(): |
|
st.error(f"{field} is required!") |
|
break |
|
if field in ["سیریل نمبر", "موبائل نمبر"] and not validate_numeric(edit_data[field]): |
|
st.error(f"{field} must be numeric!") |
|
break |
|
else: |
|
if edit_data["موبائل نمبر"] != customer["موبائل نمبر"] and edit_data["موبائل نمبر"] in st.session_state.df["موبائل نمبر"].astype(str).values: |
|
st.error("موبائل نمبر پہلے سے موجود ہے!") |
|
elif edit_data["سیریل نمبر"] != customer["سیریل نمبر"] and edit_data["سیریل نمبر"] in st.session_state.df["سیریل نمبر"].astype(str).values: |
|
st.error("سیریل نمبر پہلے سے موجود ہے!") |
|
else: |
|
edit_data["تاریخ و وقت"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
index = customer_data.index[0] |
|
for field, value in edit_data.items(): |
|
st.session_state.df.at[index, field] = value |
|
save_data(st.session_state.df) |
|
st.success("Customer updated successfully!") |
|
st.session_state.selected_phone = None |
|
|
|
|
|
delete_phone = st.text_input("Enter Phone Number to Delete:", key="delete_phone") |
|
if st.button("Delete Customer"): |
|
if delete_phone: |
|
if st.checkbox("Confirm deletion"): |
|
customer_data = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) == delete_phone] |
|
if not customer_data.empty: |
|
st.session_state.df = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) != delete_phone] |
|
save_data(st.session_state.df) |
|
st.success("Customer deleted successfully!") |
|
else: |
|
st.error("Customer not found!") |
|
else: |
|
st.warning("Please confirm deletion!") |
|
else: |
|
st.warning("Please enter a phone number!") |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
if st.button("Export All to Images"): |
|
for _, row in st.session_state.df.iterrows(): |
|
serial = row["سیریل نمبر"] |
|
name = row["گاہک کا نام"].replace("/", "_").replace("\\", "_").replace(":", "_").replace("*", "_").replace("?", "_").replace("\"", "_").replace("<", "_").replace(">", "_").replace("|", "_") |
|
filename = f"{serial}_{name}.png" |
|
create_image_from_details(row, filename) |
|
st.success("All records exported to images!") |
|
|
|
with col2: |
|
export_phone = st.text_input("Enter Phone Number to Export:", key="export_phone") |
|
if st.button("Export Selected to Image"): |
|
if export_phone: |
|
customer_data = st.session_state.df[st.session_state.df["موبائل نمبر"].astype(str) == export_phone] |
|
if not customer_data.empty: |
|
customer = customer_data.iloc[0] |
|
serial = customer["سیریل نمبر"] |
|
name = customer["گاہک کا نام"].replace("/", "_").replace("\\", "_").replace(":", "_").replace("*", "_").replace("?", "_").replace("\"", "_").replace("<", "_").replace(">", "_").replace("|", "_") |
|
filename = f"{serial}_{name}.png" |
|
create_image_from_details(customer, filename) |
|
st.success(f"Record exported to {filename}") |
|
with open(os.path.join(EXPORT_DIR, filename), "rb") as f: |
|
st.download_button("Download Image", f, file_name=filename) |
|
else: |
|
st.error("Customer not found!") |
|
else: |
|
st.warning("Please enter a phone number!") |
|
|
|
if __name__ == "__main__": |
|
main() |