grafik laporan penjualan
This commit is contained in:
parent
a2c374242f
commit
a645ee5d5b
BIN
lap/tes3.png
Normal file
BIN
lap/tes3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
lap/tes4.png
Normal file
BIN
lap/tes4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
BIN
lap/tes5.png
Normal file
BIN
lap/tes5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
138
main.py
138
main.py
@ -3316,7 +3316,14 @@ class App:
|
||||
text="💾 Export Laporan",
|
||||
command=self.export_report_to_file,
|
||||
style="Accent.TButton"
|
||||
).grid(row=3, column=0, pady=10)
|
||||
).grid(row=3, column=0, pady=(10, 5))
|
||||
|
||||
ttk.Button(
|
||||
filter_frame,
|
||||
text="🖼️ Export Grafik (PNG)",
|
||||
command=self.export_report_chart,
|
||||
style="Accent.TButton"
|
||||
).grid(row=4, column=0, pady=5)
|
||||
|
||||
# Summary frame
|
||||
summary_frame = ttk.LabelFrame(parent, text="📈 Ringkasan", padding=10)
|
||||
@ -3851,6 +3858,135 @@ class App:
|
||||
# Fallback: Tampilkan grafik ASCII sederhana
|
||||
self.show_text_chart()
|
||||
|
||||
def export_report_chart(self):
|
||||
"""Export grafik laporan ke file gambar (PNG) - REVISI FREKUENSI TRANSAKSI"""
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.ticker import MaxNLocator # Untuk sumbu Y bilangan bulat
|
||||
from datetime import datetime
|
||||
except ImportError:
|
||||
messagebox.showerror("Error", "Modul 'matplotlib' belum terinstall.\nSilakan install dengan: pip install matplotlib")
|
||||
return
|
||||
|
||||
# 1. Cek Data
|
||||
if not self.report_tree.get_children():
|
||||
messagebox.showwarning("Data Kosong", "Generate laporan terlebih dahulu sebelum export grafik.")
|
||||
return
|
||||
|
||||
# Ambil periode saat ini ('harian', 'mingguan', atau 'bulanan')
|
||||
periode_pilihan = self.report_period_var.get()
|
||||
|
||||
# 2. Kumpulkan Data dari Treeview
|
||||
metode_counts = {}
|
||||
trend_data = {} # Bisa per jam atau per hari tergantung periode
|
||||
|
||||
for item_id in self.report_tree.get_children():
|
||||
values = self.report_tree.item(item_id)['values']
|
||||
# Format values: (tid, tanggal, meja, total_str, metode, status)
|
||||
tanggal_str = values[1] # Format: DD/MM/YYYY HH:MM
|
||||
metode = values[4]
|
||||
|
||||
# Hitung Pie Chart (Metode)
|
||||
metode_counts[metode] = metode_counts.get(metode, 0) + 1
|
||||
|
||||
# Hitung Bar Chart (Trend Transaksi)
|
||||
try:
|
||||
dt_obj = datetime.strptime(tanggal_str, "%d/%m/%Y %H:%M")
|
||||
|
||||
if periode_pilihan == 'harian':
|
||||
# Jika Harian: Group by JAM (misal "14:00")
|
||||
key = dt_obj.strftime("%H:00")
|
||||
else:
|
||||
# Jika Mingguan/Bulanan: Group by TANGGAL (misal "2025-12-14")
|
||||
key = dt_obj.strftime("%Y-%m-%d")
|
||||
|
||||
# Kita hitung JUMLAH TRANSAKSI (+1), bukan total uang
|
||||
trend_data[key] = trend_data.get(key, 0) + 1
|
||||
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# 3. Buat Figure & Plotting
|
||||
try:
|
||||
# Setup layout: 1 Baris, 2 Kolom
|
||||
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 7))
|
||||
|
||||
judul_periode = periode_pilihan.upper()
|
||||
fig.suptitle(f'LAPORAN TRANSAKSI - {judul_periode}', fontsize=16, fontweight='bold')
|
||||
|
||||
# --- PLOT 1: PIE CHART (Metode Pembayaran) ---
|
||||
if metode_counts:
|
||||
labels = list(metode_counts.keys())
|
||||
sizes = list(metode_counts.values())
|
||||
# Warna-warni pastel agar cantik
|
||||
colors = ['#ff9999','#66b3ff','#99ff99','#ffcc99', '#c2c2f0']
|
||||
ax1.pie(sizes, labels=labels, autopct='%1.0f%%', colors=colors[:len(labels)], startangle=90, shadow=True)
|
||||
ax1.set_title('Proporsi Metode Pembayaran')
|
||||
else:
|
||||
ax1.text(0.5, 0.5, "Tidak ada data", ha='center')
|
||||
|
||||
# --- PLOT 2: BAR CHART (Trend Frekuensi Transaksi) ---
|
||||
if trend_data:
|
||||
keys = sorted(trend_data.keys())
|
||||
counts = [trend_data[k] for k in keys]
|
||||
|
||||
# Label X-Axis (Formatting agar rapi)
|
||||
if periode_pilihan == 'harian':
|
||||
# Label jam tetap apa adanya
|
||||
x_labels = keys
|
||||
x_title = "Jam Transaksi"
|
||||
chart_title = "Jumlah Transaksi per Jam (Busy Hours)"
|
||||
else:
|
||||
# Format tanggal jadi lebih pendek (DD/MM)
|
||||
x_labels = [datetime.strptime(k, "%Y-%m-%d").strftime("%d/%m") for k in keys]
|
||||
x_title = "Tanggal"
|
||||
chart_title = "Total Transaksi per Hari"
|
||||
|
||||
bars = ax2.bar(x_labels, counts, color='#4ECDC4', zorder=3, edgecolor='black', linewidth=0.7)
|
||||
|
||||
ax2.set_title(chart_title)
|
||||
ax2.set_xlabel(x_title)
|
||||
ax2.set_ylabel('Jumlah Transaksi (Struk)')
|
||||
|
||||
# Grid garis putus-putus di belakang
|
||||
ax2.grid(axis='y', linestyle='--', alpha=0.5, zorder=0)
|
||||
|
||||
# Pastikan Sumbu Y hanya menampilkan Angka Bulat (Integer)
|
||||
# Karena tidak mungkin ada 1.5 transaksi
|
||||
ax2.yaxis.set_major_locator(MaxNLocator(integer=True))
|
||||
|
||||
# Tambah label angka di atas setiap batang
|
||||
for bar in bars:
|
||||
height = bar.get_height()
|
||||
ax2.text(bar.get_x() + bar.get_width()/2., height,
|
||||
f'{int(height)}',
|
||||
ha='center', va='bottom', fontsize=10, fontweight='bold')
|
||||
|
||||
# Putar label x jika data banyak agar tidak tabrakan
|
||||
if len(x_labels) > 5:
|
||||
plt.setp(ax2.get_xticklabels(), rotation=45, ha="right")
|
||||
|
||||
else:
|
||||
ax2.text(0.5, 0.5, "Tidak ada data transaksi", ha='center')
|
||||
|
||||
plt.tight_layout()
|
||||
|
||||
# 4. Dialog Simpan File
|
||||
filename = filedialog.asksaveasfilename(
|
||||
defaultextension=".png",
|
||||
filetypes=[("PNG Image", "*.png"), ("JPEG Image", "*.jpg")],
|
||||
title="Simpan Grafik Statistik"
|
||||
)
|
||||
|
||||
if filename:
|
||||
plt.savefig(filename, dpi=150, bbox_inches='tight')
|
||||
messagebox.showinfo("Sukses", f"Grafik berhasil disimpan:\n{filename}")
|
||||
|
||||
plt.close(fig)
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Export Gagal", f"Terjadi kesalahan: {e}")
|
||||
|
||||
|
||||
|
||||
def reload_payment_orders(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user