noranisa commited on
Commit
ee19706
·
verified ·
1 Parent(s): 3e29d81

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -8
app.py CHANGED
@@ -2,12 +2,14 @@ import os
2
  import base64
3
  import io
4
  from functools import wraps
5
- import qrcode
6
 
7
- from flask import Flask, render_template, request, Response
 
8
  from flask_sqlalchemy import SQLAlchemy
9
  from flask_admin import Admin, AdminIndexView
10
  from flask_admin.contrib.sqla import ModelView
 
11
 
12
  # --- KONFIGURASI APLIKASI ---
13
  app = Flask(__name__)
@@ -16,6 +18,7 @@ app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default-super-secret-ke
16
  # --- KONFIGURASI DATABASE ---
17
  # Gunakan direktori /tmp yang dijamin bisa ditulisi di semua lingkungan container.
18
  DATA_DIR = '/tmp'
 
19
  os.makedirs(DATA_DIR, exist_ok=True)
20
 
21
  # Tentukan path lengkap ke file database di dalam direktori /tmp
@@ -36,6 +39,24 @@ class Product(db.Model):
36
  def __repr__(self):
37
  return f'<Product {self.name}>'
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  # --- INISIALISASI DATABASE OTOMATIS ---
41
  with app.app_context():
@@ -65,18 +86,66 @@ def protected(f):
65
 
66
 
67
  # --- PENGATURAN ADMIN PANEL ---
68
- class SecureAdminIndexView(AdminIndexView):
69
- @protected
70
- def dispatch_request(self, *args, **kwargs):
71
- return super(SecureAdminIndexView, self).dispatch_request(*args, **kwargs)
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  class SecureModelView(ModelView):
74
  @protected
75
  def dispatch_request(self, *args, **kwargs):
76
  return super(SecureModelView, self).dispatch_request(*args, **kwargs)
77
 
78
- admin = Admin(app, name='Bit & Bean Admin', template_mode='bootstrap4', index_view=SecureAdminIndexView())
 
 
 
 
79
  admin.add_view(SecureModelView(Product, db.session))
 
 
80
 
81
 
82
  # --- FUNGSI QR CODE ---
@@ -97,7 +166,9 @@ def home():
97
  products_from_db = Product.query.all()
98
  products_with_qr = []
99
  for product in products_from_db:
100
- product_url = f"https://BitBean-company.hf.space/product/{product.id}" # Sesuai URL Anda
 
 
101
  product_data = {
102
  "id": product.id,
103
  "name": product.name,
@@ -107,4 +178,5 @@ def home():
107
  "qr_code": generate_qr_code(product_url)
108
  }
109
  products_with_qr.append(product_data)
 
110
  return render_template('index.html', products=products_with_qr)
 
2
  import base64
3
  import io
4
  from functools import wraps
5
+ from datetime import datetime, date, timedelta
6
 
7
+ import qrcode
8
+ from flask import Flask, render_template, request, Response, url_for
9
  from flask_sqlalchemy import SQLAlchemy
10
  from flask_admin import Admin, AdminIndexView
11
  from flask_admin.contrib.sqla import ModelView
12
+ from sqlalchemy import func
13
 
14
  # --- KONFIGURASI APLIKASI ---
15
  app = Flask(__name__)
 
18
  # --- KONFIGURASI DATABASE ---
19
  # Gunakan direktori /tmp yang dijamin bisa ditulisi di semua lingkungan container.
20
  DATA_DIR = '/tmp'
21
+ # Pastikan direktori ada, buat jika belum ada.
22
  os.makedirs(DATA_DIR, exist_ok=True)
23
 
24
  # Tentukan path lengkap ke file database di dalam direktori /tmp
 
39
  def __repr__(self):
40
  return f'<Product {self.name}>'
41
 
42
+ class Setting(db.Model):
43
+ id = db.Column(db.Integer, primary_key=True)
44
+ key = db.Column(db.String(50), unique=True, nullable=False)
45
+ value = db.Column(db.Text, nullable=True)
46
+
47
+ def __repr__(self):
48
+ return f'<Setting {self.key}>'
49
+
50
+ class Sale(db.Model):
51
+ id = db.Column(db.Integer, primary_key=True)
52
+ product_name = db.Column(db.String(100), nullable=False)
53
+ quantity = db.Column(db.Integer, nullable=False)
54
+ total_price = db.Column(db.Float, nullable=False)
55
+ sale_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
56
+
57
+ def __repr__(self):
58
+ return f'<Sale of {self.product_name}>'
59
+
60
 
61
  # --- INISIALISASI DATABASE OTOMATIS ---
62
  with app.app_context():
 
86
 
87
 
88
  # --- PENGATURAN ADMIN PANEL ---
 
 
 
 
89
 
90
+ # Buat Dashboard View kustom kita
91
+ class DashboardView(AdminIndexView):
92
+ def get_setting(self, key, default=''):
93
+ """Helper untuk mengambil nilai dari tabel Setting."""
94
+ setting = Setting.query.filter_by(key=key).first()
95
+ return setting.value if setting else default
96
+
97
+ def get_sales_data(self):
98
+ """Query data penjualan untuk 7 hari terakhir."""
99
+ today = date.today()
100
+ seven_days_ago = today - timedelta(days=6)
101
+
102
+ sales = db.session.query(
103
+ func.date(Sale.sale_date).label('date'),
104
+ func.sum(Sale.total_price).label('total')
105
+ ).filter(
106
+ Sale.sale_date >= seven_days_ago
107
+ ).group_by(
108
+ func.date(Sale.sale_date)
109
+ ).order_by(
110
+ func.date(Sale.sale_date)
111
+ ).all()
112
+
113
+ # Buat dictionary untuk memetakan tanggal ke total penjualan
114
+ sales_dict = {s.date.strftime('%Y-%m-%d'): s.total for s in sales}
115
+
116
+ # Siapkan label dan data untuk 7 hari terakhir, isi 0 jika tidak ada penjualan
117
+ labels = [(today - timedelta(days=i)).strftime('%a, %d') for i in range(6, -1, -1)]
118
+ data = [sales_dict.get((today - timedelta(days=i)).strftime('%Y-%m-%d'), 0) for i in range(6, -1, -1)]
119
+
120
+ return labels, data
121
+
122
+ @protected # Pastikan dashboard ini juga dilindungi password
123
+ def index(self):
124
+ cafe_name = self.get_setting('cafe_name', 'Bit & Bean Coffee')
125
+ logo_url = self.get_setting('logo_url', url_for('static', filename='img/logo.png'))
126
+
127
+ chart_labels, chart_data = self.get_sales_data()
128
+
129
+ return self.render('admin/dashboard.html',
130
+ cafe_name=cafe_name,
131
+ logo_url=logo_url,
132
+ chart_labels=chart_labels,
133
+ chart_data=chart_data)
134
+
135
+ # Buat ModelView yang aman
136
  class SecureModelView(ModelView):
137
  @protected
138
  def dispatch_request(self, *args, **kwargs):
139
  return super(SecureModelView, self).dispatch_request(*args, **kwargs)
140
 
141
+ # Inisialisasi admin dengan DashboardView kustom kita
142
+ admin = Admin(app, name='Bit & Bean Dashboard', template_mode='bootstrap4',
143
+ index_view=DashboardView(name='Dashboard', url='/admin'))
144
+
145
+ # Tambahkan semua model ke admin panel
146
  admin.add_view(SecureModelView(Product, db.session))
147
+ admin.add_view(SecureModelView(Sale, db.session, category='Laporan'))
148
+ admin.add_view(SecureModelView(Setting, db.session, category='Pengaturan'))
149
 
150
 
151
  # --- FUNGSI QR CODE ---
 
166
  products_from_db = Product.query.all()
167
  products_with_qr = []
168
  for product in products_from_db:
169
+ # !! PENTING: Pastikan URL ini sesuai dengan URL Hugging Face Space Anda !!
170
+ product_url = f"https://BitBean-company.hf.space/product/{product.id}"
171
+
172
  product_data = {
173
  "id": product.id,
174
  "name": product.name,
 
178
  "qr_code": generate_qr_code(product_url)
179
  }
180
  products_with_qr.append(product_data)
181
+
182
  return render_template('index.html', products=products_with_qr)