Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import calendar | |
| from datetime import datetime, timedelta | |
| import tempfile | |
| from openpyxl import load_workbook | |
| from openpyxl.utils import column_index_from_string | |
| # 1) Define Indonesian month names | |
| MONTHS_ID = [ | |
| "Januari", "Februari", "Maret", "April", "Mei", "Juni", | |
| "Juli", "Agustus", "September", "Oktober", "November", "Desember" | |
| ] | |
| # Core report-generation function | |
| def generate_report(month, year, prev_file_path, template_file_path): | |
| if not prev_file_path or not template_file_path: | |
| raise gr.Error("Please upload both the previous report and the template.") | |
| # Determine month numbers | |
| month_num = MONTHS_ID.index(month) + 1 | |
| prev_month_num = 12 if month_num == 1 else month_num - 1 | |
| prev_year = year - 1 if month_num == 1 else year | |
| # Generate 31-day sequences for current and previous month | |
| start_current = datetime(year, month_num, 1) | |
| date_list_current = [start_current + timedelta(days=i) for i in range(31)] | |
| start_prev = datetime(prev_year, prev_month_num, 1) | |
| date_list_prev = [start_prev + timedelta(days=i) for i in range(31)] | |
| # Load template workbook and get TOTAL sheet | |
| wb_template = load_workbook(template_file_path) | |
| if 'TOTAL' not in wb_template.sheetnames: | |
| raise gr.Error("Template workbook must contain a 'TOTAL' sheet.") | |
| sheet = wb_template['TOTAL'] | |
| sheet_target = wb_template['Target'] | |
| sheet_piutang = wb_template['PIUTANG'] | |
| # Set report title | |
| sheet.merge_cells('T1:AP1') | |
| title_cell = sheet['T1'] | |
| title_cell.value = f"Laporan Keuangan {month} {year}" | |
| title_cell.alignment = title_cell.alignment.copy(horizontal='center', vertical='center') | |
| # Fill dates for current month in specified ranges | |
| current_ranges = [ | |
| ('O', 9, 39), | |
| ('T', 9, 39), | |
| ('T', 48, 78), | |
| ('T', 131, 161) | |
| ] | |
| for col_letter, start_row, end_row in current_ranges: | |
| for idx, row in enumerate(range(start_row, end_row + 1)): | |
| cell = sheet[f"{col_letter}{row}"] | |
| cell.value = date_list_current[idx] | |
| cell.number_format = 'DD/MM/YYYY' | |
| # Fill dates for previous month only in T88:T118 | |
| for idx, row in enumerate(range(88, 119)): | |
| cell = sheet[f"T{row}"] | |
| cell.value = date_list_prev[idx] | |
| cell.number_format = 'DD/MM/YYYY' | |
| # Copy block U88:AN161 from previous TOTAL sheet into template at same rows (U88:AN161) | |
| wb_prev = load_workbook(prev_file_path, data_only=True) | |
| if 'TOTAL' not in wb_prev.sheetnames: | |
| raise gr.Error("Previous workbook must contain a 'TOTAL' sheet.") | |
| sheet_prev = wb_prev['TOTAL'] | |
| sheet_prev_target = wb_prev['Target'] | |
| sheet_prev_piutang = wb_prev['PIUTANG'] | |
| sheet_setting = wb_template['Setting'] # Access the 'Setting' sheet | |
| # Set the dropdown value in cell E6 under 'Setting' tab | |
| sheet_setting['E6'].value = month # Set the value of E6 to the selected month | |
| src_start_col = column_index_from_string('U') | |
| src_end_col = column_index_from_string('AN') | |
| src_start_row = 131 | |
| src_end_row = 162 # rows 88 through 161 | |
| dest_start_row = 88 # same starting row in template | |
| row_offset = dest_start_row - src_start_row # should be 0 | |
| for col in range(src_start_col, src_end_col + 1): | |
| for row in range(src_start_row, src_end_row + 1): | |
| val = sheet_prev.cell(row=row, column=col).value | |
| # Write into same row in template | |
| dest_cell = sheet.cell(row=row + row_offset, column=col) | |
| dest_cell.value = val | |
| # 0) Copy C3:I8 -> C22:I27 on Target sheet (values only) | |
| c_start, c_end = column_index_from_string('C'), column_index_from_string('I') | |
| offset_t1 = 22 - 3 | |
| for col in range(c_start, c_end + 1): | |
| for row in range(3, 9): | |
| val = sheet_prev_target.cell(row=row, column=col).value | |
| sheet_target.cell(row=row + offset_t1, column=col).value = val | |
| # 1) Copy C11:G15 -> C30:G34 on Target sheet (values only) | |
| c_start2, c_end2 = column_index_from_string('C'), column_index_from_string('G') | |
| offset_t2 = 30 - 11 | |
| for col in range(c_start2, c_end2 + 1): | |
| for row in range(11, 16): | |
| val = sheet_prev_target.cell(row=row, column=col).value | |
| sheet_target.cell(row=row + offset_t2, column=col).value = val | |
| # 2) Copy C11:G15 -> C30:G34 (from previous Target sheet) | |
| sc2, ec2 = column_index_from_string('C'), column_index_from_string('G') | |
| offset2 = 30 - 11 | |
| for col in range(sc2, ec2+1): | |
| for row in range(11,16): | |
| val = sheet_prev_target.cell(row=row, column=col).value | |
| sheet_target.cell(row=row+offset2, column=col).value = val | |
| # 3) Copy AK38:AQ39 -> B39:H40 (from previous TOTAL sheet) | |
| ak_columns = ['AK','AL','AM','AN','AO','AP','AQ'] | |
| for i, src_row in enumerate([38,39]): | |
| for j, col_letter in enumerate(ak_columns): | |
| col_idx = column_index_from_string(col_letter) | |
| val = sheet_prev.cell(row=src_row, column=col_idx).value | |
| sheet_target.cell(row=39+i, column=2+j).value = val | |
| # 4) PIUTANG: entries on last calendar day of prev month -> B49:D? | |
| last_day = calendar.monthrange(prev_year, prev_month_num)[1] | |
| rows = [] | |
| for r in range(2, sheet_prev_piutang.max_row+1): | |
| d = sheet_prev_piutang.cell(row=r, column=1).value | |
| if isinstance(d, datetime) and d.month==prev_month_num and d.year==prev_year and d.day==last_day: | |
| rows.append(r) | |
| for idx, r in enumerate(rows): | |
| sheet_target.cell(row=49+idx, column=2).value = sheet_prev_piutang.cell(row=r, column=1).value | |
| sheet_target.cell(row=49+idx, column=3).value = sheet_prev_piutang.cell(row=r, column=2).value | |
| sheet_target.cell(row=49+idx, column=4).value = sheet_prev_piutang.cell(row=r, column=3).value | |
| for col in ['A', 'B', 'C', 'E', 'F', 'G']: | |
| for row in range(3, 501): # rows 3 to 100 inclusive | |
| sheet_piutang[f"{col}{row}"].value = None | |
| # Save and return temporary file path | |
| tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") | |
| wb_template.save(tmp.name) | |
| tmp.close() | |
| return tmp.name | |
| tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") | |
| wb_template.save(tmp.name) | |
| tmp.close() | |
| return tmp.name | |
| # Gradio UI components | |
| dropdown_month = gr.Dropdown( | |
| choices=MONTHS_ID, | |
| label="Pilih Bulan", | |
| value=MONTHS_ID[datetime.now().month - 1] | |
| ) | |
| number_year = gr.Number( | |
| label="Tahun", | |
| value=datetime.now().year, | |
| precision=0 | |
| ) | |
| file_prev = gr.File( | |
| label="Laporan Bulan Sebelumnya (.xlsx)", | |
| file_count="single", | |
| type="filepath" | |
| ) | |
| file_template = gr.File( | |
| label="Template Laporan (.xlsx)", | |
| file_count="single", | |
| type="filepath" | |
| ) | |
| iface = gr.Interface( | |
| fn=generate_report, | |
| inputs=[dropdown_month, number_year, file_prev, file_template], | |
| outputs=[gr.File(label="Unduh Laporan", type="filepath")], | |
| title="Pembuatan Laporan J&T Otomatis", | |
| allow_flagging='never' | |
| ) | |
| if __name__ == '__main__': | |
| iface.launch(share=True, server_name="0.0.0.0", server_port=7860) | |