Edoruin commited on
Commit
f9d26ad
·
1 Parent(s): ceb9831

sustitude flet by flask

Browse files
Files changed (2) hide show
  1. app/main.py +36 -3
  2. app/templates/prestamos.html +34 -4
app/main.py CHANGED
@@ -11,6 +11,7 @@ import datetime
11
  from flask import Flask, render_template, request, jsonify, redirect, url_for, flash
12
  from flask_socketio import SocketIO, emit
13
  from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
 
14
  import mysql.connector
15
  import gitlab
16
  import telebot
@@ -207,12 +208,11 @@ def login():
207
  return render_template('login.html')
208
 
209
  cursor = conn.cursor(dictionary=True)
210
- # NOTA: En producción usar hashing (e.g. werkzeug.security)
211
- cursor.execute("SELECT id, username FROM users WHERE username = %s AND password = %s", (username, password))
212
  user_data = cursor.fetchone()
213
  conn.close()
214
 
215
- if user_data:
216
  user = User(str(user_data['id']), user_data['username'])
217
  login_user(user)
218
  flash(f"¡Bienvenido, {username}!", "green")
@@ -281,6 +281,39 @@ def api_prestamo():
281
  loan_mgr.add_loan(nuevo)
282
  return jsonify({"status": "success", "id": loan_id})
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  @app.route('/repos')
285
  @login_required
286
  def repos():
 
11
  from flask import Flask, render_template, request, jsonify, redirect, url_for, flash
12
  from flask_socketio import SocketIO, emit
13
  from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
14
+ from werkzeug.security import generate_password_hash, check_password_hash
15
  import mysql.connector
16
  import gitlab
17
  import telebot
 
208
  return render_template('login.html')
209
 
210
  cursor = conn.cursor(dictionary=True)
211
+ cursor.execute("SELECT id, username, password FROM users WHERE username = %s", (username,))
 
212
  user_data = cursor.fetchone()
213
  conn.close()
214
 
215
+ if user_data and check_password_hash(user_data['password'], password):
216
  user = User(str(user_data['id']), user_data['username'])
217
  login_user(user)
218
  flash(f"¡Bienvenido, {username}!", "green")
 
281
  loan_mgr.add_loan(nuevo)
282
  return jsonify({"status": "success", "id": loan_id})
283
 
284
+ @app.route('/api/entregar/<loan_id>', methods=['POST'])
285
+ def api_entregar(loan_id):
286
+ loan = None
287
+ for l in loan_mgr.get_all():
288
+ if l['id'] == loan_id:
289
+ loan = l
290
+ break
291
+
292
+ if not loan:
293
+ return jsonify({"status": "error", "message": "Préstamo no encontrado"}), 404
294
+
295
+ if loan['status_loan'] != "ACCEPTED":
296
+ return jsonify({"status": "error", "message": "Solo se pueden entregar préstamos aceptados"}), 400
297
+
298
+ ahora = datetime.datetime.now().strftime("%H:%M")
299
+ loan_mgr.update_status(loan_id, "DELIVERED")
300
+
301
+ mensaje_tg = (
302
+ "📦 *ENTREGA DE MATERIALES*\n"
303
+ f"👤 *Solicitante:* {escape_md(loan['Solicitante'])}\n"
304
+ f"⏰ *Hora de entrega:* {ahora}\n"
305
+ f"🛠 *Items:* {escape_md(loan['item'])}"
306
+ )
307
+
308
+ if bot and TG_CHAT_ID:
309
+ try:
310
+ bot.send_message(TG_CHAT_ID, mensaje_tg, parse_mode="Markdown")
311
+ except Exception as e:
312
+ print(f"Error Telegram Entregar: {e}")
313
+
314
+ socketio.emit('notification', {"text": f"Entrega confirmada para {loan['Solicitante']}", "color": "blue"})
315
+ return jsonify({"status": "success"})
316
+
317
  @app.route('/repos')
318
  @login_required
319
  def repos():
app/templates/prestamos.html CHANGED
@@ -84,6 +84,8 @@
84
  <div style="text-align: right;">
85
  {% if loan.status_loan == 'ACCEPTED' %}
86
  <i class="fas fa-check-circle" style="color: #10b981; font-size: 1.5rem;"></i>
 
 
87
  {% elif loan.status_loan == 'DECLINED' %}
88
  <i class="fas fa-times-circle" style="color: #ef4444; font-size: 1.5rem;"></i>
89
  {% else %}
@@ -183,12 +185,18 @@
183
  const modal = document.getElementById('modal-content');
184
  const overlay = document.getElementById('modal-overlay');
185
 
186
- const statusColor = loan.status_loan === 'ACCEPTED' ? '#10b981' : (loan.status_loan === 'DECLINED' ? '#ef4444' : '#f59e0b');
 
 
 
 
 
 
187
 
188
  modal.innerHTML = `
189
  <h2 style="font-family:'Outfit'; text-align:center; margin-bottom:1.5rem;">RECIBO DE PRÉSTAMO</h2>
190
- <div style="background:${statusColor}; color:white; padding:0.5rem; border-radius:8px; text-align:center; font-weight:bold; margin-bottom:1.5rem;">
191
- ESTADO: ${loan.status_loan}
192
  </div>
193
  <p><strong>SOLICITANTE:</strong> ${loan.Solicitante}</p>
194
  <p><strong>SALIDA:</strong> ${loan.hora}</p>
@@ -196,12 +204,34 @@
196
  <hr style="opacity:0.1; margin:1rem 0;">
197
  <p><strong>HERRAMIENTAS:</strong></p>
198
  <p style="white-space:pre-wrap; font-size:0.9rem;">${loan.item}</p>
199
- <button class="btn btn-primary" style="width:100%; margin-top:1.5rem;" onclick="closeModal()">Cerrar</button>
 
 
 
 
 
 
 
 
200
  `;
201
  modal.style.display = 'block';
202
  overlay.style.display = 'block';
203
  }
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  function closeModal() {
206
  document.getElementById('modal-content').style.display = 'none';
207
  document.getElementById('modal-overlay').style.display = 'none';
 
84
  <div style="text-align: right;">
85
  {% if loan.status_loan == 'ACCEPTED' %}
86
  <i class="fas fa-check-circle" style="color: #10b981; font-size: 1.5rem;"></i>
87
+ {% elif loan.status_loan == 'DELIVERED' %}
88
+ <i class="fas fa-box" style="color: #3b82f6; font-size: 1.5rem;"></i>
89
  {% elif loan.status_loan == 'DECLINED' %}
90
  <i class="fas fa-times-circle" style="color: #ef4444; font-size: 1.5rem;"></i>
91
  {% else %}
 
185
  const modal = document.getElementById('modal-content');
186
  const overlay = document.getElementById('modal-overlay');
187
 
188
+ const statusConfig = {
189
+ 'ACCEPTED': { color: '#10b981', label: 'ACEPTADO', canDeliver: true },
190
+ 'DELIVERED': { color: '#3b82f6', label: 'ENTREGADO', canDeliver: false },
191
+ 'DECLINED': { color: '#ef4444', label: 'DECLINADO', canDeliver: false },
192
+ 'PENDING': { color: '#f59e0b', label: 'PENDIENTE', canDeliver: false }
193
+ };
194
+ const config = statusConfig[loan.status_loan] || statusConfig['PENDING'];
195
 
196
  modal.innerHTML = `
197
  <h2 style="font-family:'Outfit'; text-align:center; margin-bottom:1.5rem;">RECIBO DE PRÉSTAMO</h2>
198
+ <div style="background:${config.color}; color:white; padding:0.5rem; border-radius:8px; text-align:center; font-weight:bold; margin-bottom:1.5rem;">
199
+ ESTADO: ${config.label}
200
  </div>
201
  <p><strong>SOLICITANTE:</strong> ${loan.Solicitante}</p>
202
  <p><strong>SALIDA:</strong> ${loan.hora}</p>
 
204
  <hr style="opacity:0.1; margin:1rem 0;">
205
  <p><strong>HERRAMIENTAS:</strong></p>
206
  <p style="white-space:pre-wrap; font-size:0.9rem;">${loan.item}</p>
207
+
208
+ <div style="display:flex; gap:1rem; margin-top:1.5rem;">
209
+ ${config.canDeliver ? `
210
+ <button class="btn" style="flex:1; background:#3b82f6; color:white;" onclick="entregarPrestamo('${loan.id}')">
211
+ <i class="fas fa-box"></i> ENTREGAR
212
+ </button>
213
+ ` : ''}
214
+ <button class="btn btn-primary" style="flex:1;" onclick="closeModal()">Cerrar</button>
215
+ </div>
216
  `;
217
  modal.style.display = 'block';
218
  overlay.style.display = 'block';
219
  }
220
 
221
+ async function entregarPrestamo(loanId) {
222
+ if (!confirm('¿Confirmar la entrega de materiales?')) return;
223
+
224
+ const response = await fetch(`/api/entregar/${loanId}`, {
225
+ method: 'POST'
226
+ });
227
+
228
+ if (response.ok) {
229
+ location.reload();
230
+ } else {
231
+ alert('Error al procesar la entrega');
232
+ }
233
+ }
234
+
235
  function closeModal() {
236
  document.getElementById('modal-content').style.display = 'none';
237
  document.getElementById('modal-overlay').style.display = 'none';