import streamlit as st import pandas as pd import numpy as np import io # Page Config st.set_page_config(page_title="Anomali THC Gabungan", layout="wide") st.title('Anomali transaksi harian Format THC Gabungan') st.write("""1. File yang dibutuhkan File menu ke-6""") st.write("""2. Rapihkan data tersebut jadi seperti contoh ini: https://drive.google.com/file/d/14Ofz53dSVRFzlFrrc8snZmmkHq7CO-R2/view?usp=drive_link""") st.write("""3. Hapus karakter spesial terlebih dahulu pada file excel nya, lengkapnya ada disini tutorialnya : https://drive.google.com/file/d/1xABUwrMatieKFsNeUbOWl2KuDh6BVLwy/view?usp=drive_link """) ## SESI UPLOAD FILE uploaded_files = st.file_uploader("Upload files", accept_multiple_files=True, type=['xlsx']) df_PDR = None @st.cache_data def load_excel(file): # Menggunakan engine openpyxl untuk file xlsx return pd.read_excel(file, engine='openpyxl') if uploaded_files: for file in uploaded_files: if file.name.lower().endswith('.xlsx') and file.name == 'Format data THC gabungan.xlsx': try: with st.spinner(f"Membaca {file.name}..."): df_PDR = load_excel(file) except Exception as e: st.error(f"Error membaca file: {e}") if df_PDR is None: st.info("Harap upload file dengan nama 'Format data THC gabungan.xlsx'") else: # --- FUNGSI PERHITUNGAN --- def ambil_3_digit_akhir(val): try: if pd.isna(val) or val == 0: return 0 return int(str(int(val))[-3:]) except: return 0 def estimasi_nominal_kecil_menabung(val): return ambil_3_digit_akhir(val) def estimasi_nominal_kecil_penarikan(val): return ambil_3_digit_akhir(val) def estimasi_uang(val): try: if pd.isna(val) or val == 0: return 0 return int(np.ceil(val / 1000.0) * 1000) except: return 0 def estimasi_nabung_2(x): return x - 500 if x > 500 else 0 def estimasi_nabung_3(x): return x + 500 if x < 500 else 0 def tf_1(row): try: if row["Estimasi Nabung 1"] < 500: return ( (row["Estimasi Nabung 1"] == row["Estimasi Nominal Kecil Menabung"]) or (row["Estimasi Nabung 3"] == row["Estimasi Nominal Kecil Menabung"]) ) else: return ( (row["Estimasi Nominal Kecil Menabung"] == row["Estimasi Nabung 1"]) or (row["Estimasi Nominal Kecil Menabung"] == row["Estimasi Nabung 2"]) ) except: return False def estimasi_penarikan_1(val): return ambil_3_digit_akhir(val) def estimasi_penarikan_2(x): return x - 500 if x > 500 else 0 def tf2(row): try: if row["Estimasi Penarikan 1"] < 500: return row["Estimasi Penarikan 1"] == row["Estimasi Nominal Kecil Penarikan"] else: return ( (row["Estimasi Nominal Kecil Penarikan"] == row["Estimasi Penarikan 1"]) or (row["Estimasi Nominal Kecil Penarikan"] == row["Estimasi Penarikan 2"]) ) except: return False def final_filter(row): return bool(row["T/F 1"] or row["T/F2"]) # --- PROSES TAMBAHAN KOLUMN --- with st.spinner("Sedang memproses anomali transaksi..."): df = df_PDR.copy() # Memastikan kolom yang dibutuhkan ada required_cols = ["Db Total", "Cr Total", "Db Total2"] missing = [c for c in required_cols if c not in df.columns] if missing: st.error(f"Kolom berikut tidak ditemukan dalam file: {missing}") else: df["Estimasi Nominal Kecil Menabung"] = df["Db Total"].apply(estimasi_nominal_kecil_menabung) df["Estimasi Nominal Kecil Penarikan"] = df["Cr Total"].apply(estimasi_nominal_kecil_penarikan) df["Estimasi Uang"] = df["Db Total2"].apply(estimasi_uang) df["Estimasi Nabung 1"] = df["Estimasi Uang"] - df["Db Total2"] df["Estimasi Nabung 2"] = df["Estimasi Nabung 1"].apply(estimasi_nabung_2) df["Estimasi Nabung 3"] = df["Estimasi Nabung 1"].apply(estimasi_nabung_3) df["Estimasi Penarikan 1"] = df["Db Total2"].apply(estimasi_penarikan_1) df["Estimasi Penarikan 2"] = df["Estimasi Penarikan 1"].apply(estimasi_penarikan_2) df["T/F 1"] = df.apply(tf_1, axis=1) df["T/F2"] = df.apply(tf2, axis=1) df["Final Filter"] = df.apply(final_filter, axis=1) # Tampilkan hasil st.success("Analisis selesai!") st.write("Preview data (20 baris pertama):") st.dataframe(df.head(20)) # Filter hanya yang anomali jika diinginkan user show_anomalies_only = st.checkbox("Tampilkan hanya transaksi anomali (Final Filter = True)") if show_anomalies_only: df_display = df[df["Final Filter"] == True] st.write(f"Ditemukan {len(df_display)} anomali.") st.dataframe(df_display) st.divider() # Download hasil sebagai Excel output = io.BytesIO() with pd.ExcelWriter(output, engine='openpyxl') as writer: df.to_excel(writer, index=False) st.download_button( label="Download Download THC Final Gabungan.xlsx", data=output.getvalue(), file_name="THC Final Gabungan.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" )