Spaces:
Sleeping
Sleeping
import gradio as gr | |
import random | |
import string | |
import datetime | |
from reportlab.lib.pagesizes import A4 | |
from reportlab.lib import colors | |
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle | |
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet | |
from reportlab.lib.units import cm | |
# Daftar produk dan kategori | |
categories = { | |
"Kategori A": ["Produk A1", "Produk A2", "Produk A3", "Produk A4", "Produk A5", "Produk A6"], | |
"Kategori B": ["Produk B1", "Produk B2", "Produk B3", "Produk B4", "Produk B5", "Produk B6"], | |
"Kategori C": ["Produk C1", "Produk C2", "Produk C3", "Produk C4", "Produk C5", "Produk C6"], | |
"Kategori D": ["Produk D1", "Produk D2", "Produk D3", "Produk D4", "Produk D5", "Produk D6"] | |
} | |
# Fungsi untuk membuat dokumen PDF | |
def create_pdf(data, filename): | |
doc = SimpleDocTemplate(filename, pagesize=A4, rightMargin=2*cm, leftMargin=2*cm, topMargin=2*cm, bottomMargin=2*cm) | |
styles = getSampleStyleSheet() | |
elements = [] | |
# Gaya teks | |
title_style = ParagraphStyle(name='Title', fontSize=16, alignment=1, spaceAfter=12) | |
normal_style = ParagraphStyle(name='Normal', fontSize=10, spaceAfter=8) | |
bold_style = ParagraphStyle(name='Bold', fontSize=10, fontName='Helvetica-Bold', spaceAfter=8) | |
# Header | |
elements.append(Paragraph("Dokumen Penawaran", title_style)) | |
elements.append(Paragraph("PT. Contoh Perusahaan", normal_style)) | |
elements.append(Paragraph("Jl. Contoh Alamat No. 123", normal_style)) | |
elements.append(Spacer(1, 0.5*cm)) | |
# Kepada Yth. | |
elements.append(Paragraph(f"Kepada Yth.", normal_style)) | |
elements.append(Paragraph(f"{data['nama_prospek']}", bold_style)) | |
elements.append(Paragraph(f"{data['alamat_prospek']}", normal_style)) | |
elements.append(Paragraph(f"Jenis Prospek: {data['jenis_prospek']}", normal_style)) | |
elements.append(Spacer(1, 0.5*cm)) | |
# Tanggal | |
elements.append(Paragraph(f"Tanggal: {data['tanggal']}", normal_style)) | |
elements.append(Spacer(1, 0.5*cm)) | |
# Tabel Produk | |
elements.append(Paragraph("Daftar Produk yang Ditawarkan:", bold_style)) | |
# Data tabel | |
table_data = [["Nama Produk", "Jumlah", "Harga (Rp)", "Total (Rp)"]] | |
sub_total = 0 | |
for p in data['produk']: | |
total = p['jumlah'] * float(p['harga']) | |
sub_total += total | |
table_data.append([p['nama'], str(p['jumlah']), f"{p['harga']:,}", f"{total:,}"]) | |
# Hitung diskon dan grand total | |
if 'diskon' in data and data['diskon']: | |
diskon_percent = float(data['diskon']) | |
diskon_amount = (diskon_percent / 100) * sub_total | |
grand_total = sub_total - diskon_amount | |
else: | |
diskon_percent = 0 | |
diskon_amount = 0 | |
grand_total = sub_total | |
# Tambahkan baris sub-total, diskon, dan grand total | |
table_data.append(["", "", "Sub-Total", f"{sub_total:,}"]) | |
if diskon_percent > 0: | |
table_data.append(["", "", f"Diskon ({diskon_percent}%)", f"-{diskon_amount:,}"]) | |
table_data.append(["", "", "Grand Total", f"{grand_total:,}"]) | |
# Buat tabel | |
table = Table(table_data, colWidths=[6*cm, 2*cm, 3*cm, 3*cm]) | |
table.setStyle(TableStyle([ | |
('BACKGROUND', (0, 0), (-1, 0), colors.grey), | |
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), | |
('ALIGN', (0, 0), (-1, -1), 'CENTER'), | |
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), | |
('FONTSIZE', (0, 0), (-1, -1), 10), | |
('BOTTOMPADDING', (0, 0), (-1, 0), 10), | |
('BACKGROUND', (0, 1), (-1, -3), colors.beige), | |
('GRID', (0, 0), (-1, -1), 1, colors.black), | |
('SPAN', (0, -2), (1, -2)), # Span sub-total | |
('SPAN', (0, -1), (1, -1)), # Span grand total | |
('ALIGN', (2, -2), (3, -1), 'CENTER'), # Align right for totals | |
])) | |
if diskon_percent > 0: | |
table.setStyle(TableStyle([ | |
('SPAN', (0, -3), (1, -3)), # Span diskon | |
])) | |
elements.append(table) | |
elements.append(Spacer(1, 0.5*cm)) | |
# Syarat dan Ketentuan | |
syarat_text = f"Syarat dan Ketentuan:<br/>{data['syarat']}" if 'syarat' in data else "Syarat dan Ketentuan: Tidak ada" | |
elements.append(Paragraph(syarat_text, normal_style)) | |
elements.append(Spacer(1, 0.5*cm)) | |
# Tanda Tangan | |
elements.append(Paragraph("Hormat kami,", normal_style)) | |
elements.append(Paragraph("PT. Contoh Perusahaan", normal_style)) | |
# Build PDF | |
doc.build(elements) | |
return filename | |
# Fungsi untuk memproses input dan membuat penawaran | |
def buat_penawaran(nama_prospek, alamat_prospek, jenis_prospek, produk_dipilih, jumlah_produk, harga_produk, diskon, tanggal, syarat): | |
data = { | |
'nama_prospek': nama_prospek if nama_prospek else "Prospek Tanpa Nama", | |
'alamat_prospek': alamat_prospek if alamat_prospek else "Alamat Tidak Diketahui", | |
'jenis_prospek': jenis_prospek if jenis_prospek else "Individu", | |
'tanggal': tanggal if tanggal else datetime.date.today().strftime("%Y-%m-%d"), | |
'produk': [] | |
} | |
# Proses produk | |
if produk_dipilih and jumlah_produk and harga_produk: | |
try: | |
jumlah_list = [int(x.strip()) for x in jumlah_produk.split(",") if x.strip()] | |
harga_list = [int(x.strip()) for x in harga_produk.split(",") if x.strip()] | |
for i, p in enumerate(produk_dipilih): | |
j = jumlah_list[i] if i < len(jumlah_list) else 1 | |
h = harga_list[i] if i < len(harga_list) else 100000 | |
data['produk'].append({'nama': p, 'jumlah': j, 'harga': h}) | |
except ValueError: | |
data['produk'].append({'nama': "Produk Contoh", 'jumlah': 1, 'harga': 100000}) | |
warning = "Peringatan: Format jumlah atau harga produk salah. Diganti dengan data contoh." | |
else: | |
data['produk'].append({'nama': "Produk Contoh", 'jumlah': 1, 'harga': 100000}) | |
if diskon: | |
try: | |
data['diskon'] = float(diskon) | |
except ValueError: | |
data['diskon'] = 0 | |
if syarat: | |
data['syarat'] = syarat | |
# Validasi data | |
missing_data = [] | |
if not nama_prospek: | |
missing_data.append("Nama Prospek") | |
if not alamat_prospek: | |
missing_data.append("Alamat Prospek") | |
if not jenis_prospek: | |
missing_data.append("Jenis Prospek") | |
if not tanggal: | |
missing_data.append("Tanggal") | |
if not produk_dipilih or not jumlah_produk or not harga_produk: | |
missing_data.append("Produk, Jumlah, atau Harga") | |
warning = "" | |
if missing_data: | |
warning = "Peringatan: Data berikut kurang dan telah diisi dengan asumsi: " + ", ".join(missing_data) + ". Silakan lengkapi data jika perlu." | |
# Buat file PDF | |
filename = ''.join(random.choices(string.ascii_letters + string.digits, k=10)) + ".pdf" | |
pdf_file = create_pdf(data, filename) | |
return pdf_file, warning | |
# Interface Gradio | |
with gr.Blocks() as demo: | |
gr.Markdown("# Aplikasi Pembuatan Dokumen Penawaran") | |
with gr.Row(): | |
nama_prospek = gr.Textbox(label="Nama Prospek") | |
alamat_prospek = gr.Textbox(label="Alamat Prospek") | |
jenis_prospek = gr.Dropdown(choices=["Individu", "Perusahaan", "Kafe"], label="Jenis Prospek") | |
with gr.Row(): | |
tanggal = gr.Textbox(label="Tanggal Penawaran (YYYY-MM-DD)") | |
with gr.Row(): | |
produk_dipilih = gr.CheckboxGroup(choices=[p for cat in categories.values() for p in cat], label="Pilih Produk") | |
jumlah_produk = gr.Textbox(label="Jumlah Produk (pisahkan dengan koma)") | |
harga_produk = gr.Textbox(label="Harga per Produk (Rp, pisahkan dengan koma)") | |
with gr.Row(): | |
diskon = gr.Textbox(label="Diskon (%)") | |
syarat = gr.Textbox(label="Syarat dan Ketentuan") | |
submit_button = gr.Button("Buat Penawaran") | |
output_file = gr.File(label="Download Dokumen Penawaran (PDF)") | |
warning_text = gr.Textbox(label="Peringatan") | |
submit_button.click( | |
buat_penawaran, | |
inputs=[nama_prospek, alamat_prospek, jenis_prospek, produk_dipilih, jumlah_produk, harga_produk, diskon, tanggal, syarat], | |
outputs=[output_file, warning_text] | |
) | |
demo.launch() |