Spaces:
Sleeping
Sleeping
| 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 | |
| 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" | |
| ) | |