dvsaudit commited on
Commit
afafb5d
·
verified ·
1 Parent(s): 6db699a

Upload 5 files

Browse files
Files changed (5) hide show
  1. Dockerfile +30 -0
  2. README.md +10 -0
  3. app.py +329 -0
  4. docker-compose.yml +13 -0
  5. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ # Set environment variables
4
+ ENV PYTHONDONTWRITEBYTECODE=1
5
+ ENV PYTHONUNBUFFERED=1
6
+
7
+ # Create a non-root user (Standard HF)
8
+ RUN useradd -m -u 1000 user
9
+ WORKDIR /home/user/app
10
+
11
+ # Install system dependencies
12
+ RUN apt-get update && apt-get install -y \
13
+ curl \
14
+ && rm -rf /var/lib/apt/lists/*
15
+
16
+ # Install python dependencies globally as root
17
+ COPY requirements.txt .
18
+ RUN pip install --no-cache-dir -r requirements.txt
19
+
20
+ # Copy application and set ownership
21
+ COPY --chown=user:user . .
22
+
23
+ # Expose port (HF requirement)
24
+ EXPOSE 7860
25
+
26
+ # Switch to user
27
+ USER user
28
+
29
+ # Run application with WebSocket & Custom Domain fixes
30
+ CMD ["python", "-m", "streamlit", "run", "app.py", "--server.port=7860", "--server.address=0.0.0.0", "--browser.gatherUsageStats=false", "--server.enableCORS=false", "--server.enableXsrfProtection=false"]
README.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: THC Gabungan
3
+ emoji: 😻
4
+ colorFrom: purple
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+ import streamlit as st
6
+
7
+
8
+ st.set_page_config(page_title="Aplikasi Pengolahan THC", layout="wide")
9
+
10
+ st.title("Aplikasi Pengolahan THC")
11
+ st.divider()
12
+ st.caption("Ini digunakan untuk menyatukan file THC FINAL, TAK, TLP dan KDP")
13
+ st.caption("Satukan terlebih dahulu file yang sudah di vlookup, di poin nomor 4 pada site pengolahan")
14
+ st.caption(":red[pivot_TLP_na.xlsx ke TLP.xlsx], :red[pivot_KDP_na.xlsx ke KDP.xlsx]")
15
+ st.divider()
16
+
17
+ st.subheader("File yang dibutuhkan:")
18
+ st.write("1. THC FINAL.xlsx")
19
+ st.write("2. TAK.xlsx")
20
+ st.write("3. TLP.xlsx")
21
+ st.write("4. KDP.xlsx")
22
+
23
+ EXPECTED_FILES = ["THC FINAL.xlsx", "TAK.xlsx", "TLP.xlsx", "KDP.xlsx"]
24
+ KEY_COLUMNS = [
25
+ "ID ANGGOTA",
26
+ "DUMMY",
27
+ "NAMA",
28
+ "CENTER",
29
+ "KEL",
30
+ "HARI",
31
+ "JAM",
32
+ "SL",
33
+ "TRANS. DATE",
34
+ ]
35
+ DESIRED_ORDER = [
36
+ "ID ANGGOTA",
37
+ "DUMMY",
38
+ "NAMA",
39
+ "CENTER",
40
+ "KEL",
41
+ "HARI",
42
+ "JAM",
43
+ "SL",
44
+ "TRANS. DATE",
45
+ "Db Qurban",
46
+ "Cr Qurban",
47
+ "Db Khusus",
48
+ "Cr Khusus",
49
+ "Db Sihara",
50
+ "Cr Sihara",
51
+ "Db Pensiun",
52
+ "Cr Pensiun",
53
+ "Db Pokok",
54
+ "Cr Pokok",
55
+ "Db SIPADAN",
56
+ "Cr SIPADAN",
57
+ "Db Sukarela",
58
+ "Cr Sukarela",
59
+ "Db Wajib",
60
+ "Cr Wajib",
61
+ "Db Total",
62
+ "Cr Total",
63
+ "Db PTN",
64
+ "Cr PTN",
65
+ "Db PRT",
66
+ "Cr PRT",
67
+ "Db DTP",
68
+ "Cr DTP",
69
+ "Db PMB",
70
+ "Cr PMB",
71
+ "Db PRR",
72
+ "Cr PRR",
73
+ "Db PSA",
74
+ "Cr PSA",
75
+ "Db PU",
76
+ "Cr PU",
77
+ "Db Total2",
78
+ "Cr Total2",
79
+ ]
80
+ NUMERIC_COLUMNS = [col for col in DESIRED_ORDER if col not in KEY_COLUMNS]
81
+
82
+
83
+ @st.cache_data(show_spinner=False)
84
+ def load_excel(file_obj):
85
+ return pd.read_excel(file_obj, engine="openpyxl")
86
+
87
+
88
+ def ensure_columns(df, columns, default_value=0):
89
+ for col in columns:
90
+ if col not in df.columns:
91
+ df[col] = default_value
92
+ return df
93
+
94
+
95
+ def process_dataframe(df, new_columns, rename_dict):
96
+ df = ensure_columns(df.copy(), new_columns)
97
+ df = df.rename(columns=rename_dict)
98
+ df = ensure_columns(df, DESIRED_ORDER)
99
+ return df[DESIRED_ORDER]
100
+
101
+
102
+ def normalize_numeric(df, numeric_columns):
103
+ df = df.copy()
104
+ for col in numeric_columns:
105
+ if col not in df.columns:
106
+ df[col] = 0
107
+ continue
108
+
109
+ cleaned = (
110
+ df[col]
111
+ .astype(str)
112
+ .str.replace(",", "", regex=False)
113
+ .str.replace(" ", "", regex=False)
114
+ )
115
+ df[col] = pd.to_numeric(cleaned, errors="coerce").fillna(0)
116
+ return df
117
+
118
+
119
+ uploaded_files = st.file_uploader(
120
+ "Unggah file Excel", accept_multiple_files=True, type=["xlsx"]
121
+ )
122
+
123
+ if uploaded_files:
124
+ dfs = {}
125
+ for file in uploaded_files:
126
+ try:
127
+ dfs[file.name] = load_excel(file)
128
+ except Exception as exc:
129
+ st.error(f"Gagal membaca {file.name}: {exc}")
130
+
131
+ missing_files = [name for name in EXPECTED_FILES if name not in dfs]
132
+ if missing_files:
133
+ st.warning(f"File yang belum diunggah: {', '.join(missing_files)}")
134
+
135
+ combined_df_list = []
136
+
137
+ if "THC FINAL.xlsx" in dfs:
138
+ df_thc = dfs["THC FINAL.xlsx"].copy()
139
+ df_thc = ensure_columns(df_thc, DESIRED_ORDER)
140
+ df_thc = df_thc[DESIRED_ORDER]
141
+ st.write("THC FINAL:")
142
+ st.dataframe(df_thc, use_container_width=True)
143
+ combined_df_list.append(df_thc)
144
+
145
+ if "TAK.xlsx" in dfs:
146
+ df_tak = dfs["TAK.xlsx"]
147
+ new_columns_tak = [
148
+ "DEBIT_PINJAMAN UMUM",
149
+ "DEBIT_PINJAMAN RENOVASI RUMAH",
150
+ "DEBIT_PINJAMAN SANITASI",
151
+ "DEBIT_PINJAMAN ARTA",
152
+ "DEBIT_PINJAMAN MIKROBISNIS",
153
+ "DEBIT_PINJAMAN DT. PENDIDIKAN",
154
+ "DEBIT_PINJAMAN PERTANIAN",
155
+ "DEBIT_TOTAL",
156
+ "CREDIT_PINJAMAN UMUM",
157
+ "CREDIT_PINJAMAN RENOVASI RUMAH",
158
+ "CREDIT_PINJAMAN SANITASI",
159
+ "CREDIT_PINJAMAN ARTA",
160
+ "CREDIT_PINJAMAN MIKROBISNIS",
161
+ "CREDIT_PINJAMAN DT. PENDIDIKAN",
162
+ "CREDIT_PINJAMAN PERTANIAN",
163
+ "CREDIT_TOTAL",
164
+ ]
165
+ rename_dict_tak = {
166
+ "KELOMPOK": "KEL",
167
+ "DEBIT_PINJAMAN ARTA": "Db PRT",
168
+ "DEBIT_PINJAMAN DT. PENDIDIKAN": "Db DTP",
169
+ "DEBIT_PINJAMAN MIKROBISNIS": "Db PMB",
170
+ "DEBIT_PINJAMAN SANITASI": "Db PSA",
171
+ "DEBIT_PINJAMAN UMUM": "Db PU",
172
+ "DEBIT_PINJAMAN RENOVASI RUMAH": "Db PRR",
173
+ "DEBIT_PINJAMAN PERTANIAN": "Db PTN",
174
+ "DEBIT_TOTAL": "Db Total2",
175
+ "CREDIT_PINJAMAN ARTA": "Cr PRT",
176
+ "CREDIT_PINJAMAN DT. PENDIDIKAN": "Cr DTP",
177
+ "CREDIT_PINJAMAN MIKROBISNIS": "Cr PMB",
178
+ "CREDIT_PINJAMAN SANITASI": "Cr PSA",
179
+ "CREDIT_PINJAMAN UMUM": "Cr PU",
180
+ "CREDIT_PINJAMAN RENOVASI RUMAH": "Cr PRR",
181
+ "CREDIT_PINJAMAN PERTANIAN": "Cr PTN",
182
+ "CREDIT_TOTAL": "Cr Total2",
183
+ }
184
+ df_tak = process_dataframe(df_tak, new_columns_tak, rename_dict_tak)
185
+ df_tak = normalize_numeric(df_tak, NUMERIC_COLUMNS)
186
+ st.write("TAK FINAL:")
187
+ st.dataframe(df_tak, use_container_width=True)
188
+ combined_df_list.append(df_tak)
189
+
190
+ if "TLP.xlsx" in dfs:
191
+ df_tlp = dfs["TLP.xlsx"]
192
+ new_columns_tlp = [
193
+ "DEBIT_Simpanan Pensiun",
194
+ "DEBIT_Simpanan Pokok",
195
+ "DEBIT_Simpanan Sukarela",
196
+ "DEBIT_Simpanan Wajib",
197
+ "DEBIT_Simpanan Hari Raya",
198
+ "DEBIT_Simpanan Qurban",
199
+ "DEBIT_Simpanan Sipadan",
200
+ "DEBIT_Simpanan Khusus",
201
+ "CREDIT_Simpanan Pensiun",
202
+ "CREDIT_Simpanan Pokok",
203
+ "CREDIT_Simpanan Sukarela",
204
+ "CREDIT_Simpanan Wajib",
205
+ "CREDIT_Simpanan Hari Raya",
206
+ "CREDIT_Simpanan Qurban",
207
+ "CREDIT_Simpanan Sipadan",
208
+ "CREDIT_Simpanan Khusus",
209
+ ]
210
+ rename_dict_tlp = {
211
+ "KELOMPOK": "KEL",
212
+ "DEBIT_Simpanan Hari Raya": "Db Sihara",
213
+ "DEBIT_Simpanan Pensiun": "Db Pensiun",
214
+ "DEBIT_Simpanan Pokok": "Db Pokok",
215
+ "DEBIT_Simpanan Sukarela": "Db Sukarela",
216
+ "DEBIT_Simpanan Wajib": "Db Wajib",
217
+ "DEBIT_Simpanan Qurban": "Db Qurban",
218
+ "DEBIT_Simpanan Sipadan": "Db SIPADAN",
219
+ "DEBIT_Simpanan Khusus": "Db Khusus",
220
+ "DEBIT_TOTAL": "Db Total",
221
+ "CREDIT_Simpanan Hari Raya": "Cr Sihara",
222
+ "CREDIT_Simpanan Pensiun": "Cr Pensiun",
223
+ "CREDIT_Simpanan Pokok": "Cr Pokok",
224
+ "CREDIT_Simpanan Sukarela": "Cr Sukarela",
225
+ "CREDIT_Simpanan Wajib": "Cr Wajib",
226
+ "CREDIT_Simpanan Qurban": "Cr Qurban",
227
+ "CREDIT_Simpanan Sipadan": "Cr SIPADAN",
228
+ "CREDIT_Simpanan Khusus": "Cr Khusus",
229
+ "CREDIT_TOTAL": "Cr Total",
230
+ }
231
+ df_tlp = process_dataframe(df_tlp, new_columns_tlp, rename_dict_tlp)
232
+ df_tlp = normalize_numeric(df_tlp, NUMERIC_COLUMNS)
233
+ st.write("TLP FINAL:")
234
+ st.dataframe(df_tlp, use_container_width=True)
235
+ combined_df_list.append(df_tlp)
236
+
237
+ if "KDP.xlsx" in dfs:
238
+ try:
239
+ df_kdp = dfs["KDP.xlsx"]
240
+ new_columns_kdp = [
241
+ "DEBIT_Simpanan Pensiun",
242
+ "DEBIT_Simpanan Pokok",
243
+ "DEBIT_Simpanan Sukarela",
244
+ "DEBIT_Simpanan Wajib",
245
+ "DEBIT_Simpanan Hari Raya",
246
+ "DEBIT_Simpanan Qurban",
247
+ "DEBIT_Simpanan Sipadan",
248
+ "DEBIT_Simpanan Khusus",
249
+ "CREDIT_Simpanan Pensiun",
250
+ "CREDIT_Simpanan Pokok",
251
+ "CREDIT_Simpanan Sukarela",
252
+ "CREDIT_Simpanan Wajib",
253
+ "CREDIT_Simpanan Hari Raya",
254
+ "CREDIT_Simpanan Qurban",
255
+ "CREDIT_Simpanan Sipadan",
256
+ "CREDIT_Simpanan Khusus",
257
+ "DEBIT_PU",
258
+ "CREDIT_PU",
259
+ "DEBIT_TOTAL2",
260
+ "CREDIT_TOTAL2",
261
+ ]
262
+ rename_dict_kdp = {
263
+ "KELOMPOK": "KEL",
264
+ "DEBIT_Simpanan Hari Raya": "Db Sihara",
265
+ "DEBIT_Simpanan Pensiun": "Db Pensiun",
266
+ "DEBIT_Simpanan Pokok": "Db Pokok",
267
+ "DEBIT_Simpanan Sukarela": "Db Sukarela",
268
+ "DEBIT_Simpanan Wajib": "Db Wajib",
269
+ "DEBIT_Simpanan Qurban": "Db Qurban",
270
+ "DEBIT_Simpanan Sipadan": "Db SIPADAN",
271
+ "DEBIT_Simpanan Khusus": "Db Khusus",
272
+ "DEBIT_TOTAL": "Db Total",
273
+ "CREDIT_Simpanan Hari Raya": "Cr Sihara",
274
+ "CREDIT_Simpanan Pensiun": "Cr Pensiun",
275
+ "CREDIT_Simpanan Pokok": "Cr Pokok",
276
+ "CREDIT_Simpanan Sukarela": "Cr Sukarela",
277
+ "CREDIT_Simpanan Wajib": "Cr Wajib",
278
+ "CREDIT_Simpanan Qurban": "Cr Qurban",
279
+ "CREDIT_Simpanan Sipadan": "Cr SIPADAN",
280
+ "CREDIT_Simpanan Khusus": "Cr Khusus",
281
+ "CREDIT_TOTAL": "Cr Total",
282
+ "DEBIT_PU": "Db PU",
283
+ "CREDIT_PU": "Cr PU",
284
+ "DEBIT_TOTAL2": "Db Total2",
285
+ "CREDIT_TOTAL2": "Cr Total2",
286
+ }
287
+
288
+ df_kdp = process_dataframe(df_kdp, new_columns_kdp, rename_dict_kdp)
289
+ df_kdp = df_kdp.loc[:, ~df_kdp.columns.duplicated()]
290
+ df_kdp = normalize_numeric(df_kdp, NUMERIC_COLUMNS)
291
+
292
+ numeric_group_cols = [col for col in NUMERIC_COLUMNS if col in df_kdp.columns]
293
+ df_kdp = df_kdp.groupby(KEY_COLUMNS, as_index=False)[numeric_group_cols].sum()
294
+
295
+ df_kdp = ensure_columns(df_kdp, DESIRED_ORDER)
296
+ df_kdp = df_kdp[DESIRED_ORDER]
297
+
298
+ st.write("KDP FINAL:")
299
+ st.dataframe(df_kdp, use_container_width=True)
300
+ combined_df_list.append(df_kdp)
301
+
302
+ except Exception as exc:
303
+ st.error(f"Error pada pemrosesan KDP: {exc}")
304
+
305
+ combined_df_list = [df for df in combined_df_list if not df.empty]
306
+
307
+ if combined_df_list:
308
+ try:
309
+ combined_df = pd.concat(combined_df_list, ignore_index=True)
310
+ combined_df = normalize_numeric(combined_df, NUMERIC_COLUMNS)
311
+
312
+ st.write("Combined DataFrame:")
313
+ st.dataframe(combined_df, use_container_width=True)
314
+
315
+ buffer = io.BytesIO()
316
+ with pd.ExcelWriter(buffer, engine="xlsxwriter") as writer:
317
+ combined_df.to_excel(writer, index=False, sheet_name="Sheet1")
318
+ buffer.seek(0)
319
+
320
+ st.download_button(
321
+ label="Unduh Format data THC gabungan.xlsx",
322
+ data=buffer.getvalue(),
323
+ file_name="Format data THC gabungan.xlsx",
324
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
325
+ )
326
+ except Exception as exc:
327
+ st.error(f"Terjadi kesalahan saat menggabungkan data: {exc}")
328
+ else:
329
+ st.error("Tidak ada DataFrame valid untuk diproses.")
docker-compose.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ thc-gabungan:
3
+ build: .
4
+ container_name: streamlit-gabungan
5
+ ports:
6
+ - "7862:7860"
7
+ restart: always
8
+ deploy:
9
+ resources:
10
+ limits:
11
+ memory: 2G
12
+ environment:
13
+ - STREAMLIT_SERVER_MAX_UPLOAD_SIZE=500
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas>=2.1.0
3
+ numpy
4
+ openpyxl
5
+ xlsxwriter
6
+ pyarrow>=12.0.0