pc responsive issues
Browse files- app/main.py +54 -39
- app/templates/prestamos.html +0 -20
app/main.py
CHANGED
|
@@ -169,6 +169,25 @@ def escape_md(text):
|
|
| 169 |
text = text.replace(char, f"\\{char}")
|
| 170 |
return text
|
| 171 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
if bot:
|
| 173 |
@bot.callback_query_handler(func=lambda call: True)
|
| 174 |
def handle_query(call):
|
|
@@ -177,9 +196,16 @@ if bot:
|
|
| 177 |
loan_id = call.data.replace("accept_", "")
|
| 178 |
if loan_mgr.update_status(loan_id, "ACCEPTED"):
|
| 179 |
bot.answer_callback_query(call.id, "Préstamo Aceptado")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
nuevo_texto = f"✅ *ACEPTADO*\n{escape_md(call.message.text)}"
|
| 181 |
-
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id,
|
|
|
|
| 182 |
socketio.emit('notification', {"text": f"Préstamo {loan_id[:8]} ACEPTADO", "color": "green"})
|
|
|
|
| 183 |
elif call.data.startswith("decline_"):
|
| 184 |
loan_id = call.data.replace("decline_", "")
|
| 185 |
if loan_mgr.update_status(loan_id, "DECLINED"):
|
|
@@ -187,22 +213,41 @@ if bot:
|
|
| 187 |
nuevo_texto = f"❌ *DECLINADO*\n{escape_md(call.message.text)}"
|
| 188 |
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 189 |
socketio.emit('notification', {"text": f"Préstamo {loan_id[:8]} DECLINADO", "color": "red"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
except Exception as e:
|
| 191 |
print(f"Callback Error: {e}")
|
| 192 |
|
| 193 |
-
@bot.message_handler(commands=['aceptar', 'declinar', 'status'])
|
| 194 |
def handle_text_commands(message):
|
| 195 |
try:
|
| 196 |
text = message.text.split()
|
| 197 |
if len(text) < 2:
|
| 198 |
-
bot.reply_to(message, "Uso: /aceptar <id> o /
|
| 199 |
return
|
| 200 |
cmd = text[0][1:]; loan_id = text[1]
|
| 201 |
-
|
| 202 |
-
if
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
except Exception as e:
|
| 207 |
print(f"Command Error: {e}")
|
| 208 |
|
|
@@ -329,37 +374,7 @@ def api_prestamo():
|
|
| 329 |
|
| 330 |
return jsonify({"status": "success", "id": loan_id})
|
| 331 |
|
| 332 |
-
|
| 333 |
-
def api_entregar(loan_id):
|
| 334 |
-
loan = None
|
| 335 |
-
for l in loan_mgr.get_all():
|
| 336 |
-
if l['id'] == loan_id:
|
| 337 |
-
loan = l
|
| 338 |
-
break
|
| 339 |
-
|
| 340 |
-
if not loan or loan['status_loan'] != "ACCEPTED":
|
| 341 |
-
return jsonify({"status": "error", "message": "No se puede entregar"}), 400
|
| 342 |
-
|
| 343 |
-
# Hora AST (Rep. Dom.)
|
| 344 |
-
utc_now = datetime.datetime.now(datetime.timezone.utc)
|
| 345 |
-
rd_now = utc_now - datetime.timedelta(hours=4)
|
| 346 |
-
ahora = rd_now.strftime("%H:%M")
|
| 347 |
-
|
| 348 |
-
loan_mgr.update_status(loan_id, "DELIVERED")
|
| 349 |
-
|
| 350 |
-
mensaje_tg = (
|
| 351 |
-
"📦 *ENTREGA DE MATERIALES*\n"
|
| 352 |
-
f"👤 *Solicitante:* {escape_md(loan['Solicitante'])}\n"
|
| 353 |
-
f"⏰ *Hora de entrega:* {ahora}\n"
|
| 354 |
-
f"🛠 *Items:* {escape_md(loan['item'])}"
|
| 355 |
-
)
|
| 356 |
-
|
| 357 |
-
if bot and TG_CHAT_ID:
|
| 358 |
-
try: bot.send_message(TG_CHAT_ID, mensaje_tg, parse_mode="Markdown")
|
| 359 |
-
except: pass
|
| 360 |
-
|
| 361 |
-
socketio.emit('notification', {"text": f"Entrega confirmada para {loan['Solicitante']}", "color": "blue"})
|
| 362 |
-
return jsonify({"status": "success"})
|
| 363 |
|
| 364 |
@app.route('/repos')
|
| 365 |
@login_required
|
|
|
|
| 169 |
text = text.replace(char, f"\\{char}")
|
| 170 |
return text
|
| 171 |
|
| 172 |
+
def mark_as_delivered(loan_id):
|
| 173 |
+
"""Lógica central para marcar un préstamo como entregado físicamente."""
|
| 174 |
+
loan = None
|
| 175 |
+
for l in loan_mgr.get_all():
|
| 176 |
+
if l['id'] == loan_id:
|
| 177 |
+
loan = l
|
| 178 |
+
break
|
| 179 |
+
|
| 180 |
+
if loan and loan['status_loan'] == "ACCEPTED":
|
| 181 |
+
# Hora AST (Rep. Dom.)
|
| 182 |
+
utc_now = datetime.datetime.now(datetime.timezone.utc)
|
| 183 |
+
rd_now = utc_now - datetime.timedelta(hours=4)
|
| 184 |
+
ahora = rd_now.strftime("%H:%M")
|
| 185 |
+
|
| 186 |
+
loan_mgr.update_status(loan_id, "DELIVERED")
|
| 187 |
+
socketio.emit('notification', {"text": f"{loan['Solicitante']} ha entregado", "color": "blue"})
|
| 188 |
+
return True, loan, ahora
|
| 189 |
+
return False, None, None
|
| 190 |
+
|
| 191 |
if bot:
|
| 192 |
@bot.callback_query_handler(func=lambda call: True)
|
| 193 |
def handle_query(call):
|
|
|
|
| 196 |
loan_id = call.data.replace("accept_", "")
|
| 197 |
if loan_mgr.update_status(loan_id, "ACCEPTED"):
|
| 198 |
bot.answer_callback_query(call.id, "Préstamo Aceptado")
|
| 199 |
+
|
| 200 |
+
# Al aceptar, añadimos el botón de "ENTREGAR" en el mismo mensaje
|
| 201 |
+
markup = types.InlineKeyboardMarkup()
|
| 202 |
+
markup.add(types.InlineKeyboardButton("📦 MARCAR ENTREGADO", callback_data=f"deliver_{loan_id}"))
|
| 203 |
+
|
| 204 |
nuevo_texto = f"✅ *ACEPTADO*\n{escape_md(call.message.text)}"
|
| 205 |
+
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id,
|
| 206 |
+
reply_markup=markup, parse_mode="Markdown")
|
| 207 |
socketio.emit('notification', {"text": f"Préstamo {loan_id[:8]} ACEPTADO", "color": "green"})
|
| 208 |
+
|
| 209 |
elif call.data.startswith("decline_"):
|
| 210 |
loan_id = call.data.replace("decline_", "")
|
| 211 |
if loan_mgr.update_status(loan_id, "DECLINED"):
|
|
|
|
| 213 |
nuevo_texto = f"❌ *DECLINADO*\n{escape_md(call.message.text)}"
|
| 214 |
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 215 |
socketio.emit('notification', {"text": f"Préstamo {loan_id[:8]} DECLINADO", "color": "red"})
|
| 216 |
+
|
| 217 |
+
elif call.data.startswith("deliver_"):
|
| 218 |
+
loan_id = call.data.replace("deliver_", "")
|
| 219 |
+
success, loan, ahora = mark_as_delivered(loan_id)
|
| 220 |
+
if success:
|
| 221 |
+
bot.answer_callback_query(call.id, "Entrega Confirmada")
|
| 222 |
+
nuevo_texto = f"📦 *ENTREGADO A LAS {ahora}*\n{escape_md(call.message.text)}"
|
| 223 |
+
bot.edit_message_text(nuevo_texto, call.message.chat.id, call.message.message_id, parse_mode="Markdown")
|
| 224 |
+
else:
|
| 225 |
+
bot.answer_callback_query(call.id, "Error: El préstamo no está aceptado o no existe", show_alert=True)
|
| 226 |
+
|
| 227 |
except Exception as e:
|
| 228 |
print(f"Callback Error: {e}")
|
| 229 |
|
| 230 |
+
@bot.message_handler(commands=['aceptar', 'declinar', 'entregado', 'status'])
|
| 231 |
def handle_text_commands(message):
|
| 232 |
try:
|
| 233 |
text = message.text.split()
|
| 234 |
if len(text) < 2:
|
| 235 |
+
bot.reply_to(message, "Uso: /aceptar <id>, /declinar <id> o /entregado <id>")
|
| 236 |
return
|
| 237 |
cmd = text[0][1:]; loan_id = text[1]
|
| 238 |
+
|
| 239 |
+
if cmd == "entregado":
|
| 240 |
+
success, loan, ahora = mark_as_delivered(loan_id)
|
| 241 |
+
if success:
|
| 242 |
+
bot.reply_to(message, f"📦 Entrega confirmada para {loan['Solicitante']} a las {ahora}")
|
| 243 |
+
else:
|
| 244 |
+
bot.reply_to(message, "No se pudo marcar como entregado. Verifica el ID y el estado.")
|
| 245 |
+
else:
|
| 246 |
+
status = "ACCEPTED" if cmd == "aceptar" else "DECLINED"
|
| 247 |
+
if loan_mgr.update_status(loan_id, status):
|
| 248 |
+
emoji = "✅" if status == "ACCEPTED" else "❌"
|
| 249 |
+
bot.reply_to(message, f"{emoji} Préstamo {loan_id} actualizado a {status}")
|
| 250 |
+
socketio.emit('notification', {"text": f"Préstamo {loan_id[:8]} {status}", "color": "green" if status == "ACCEPTED" else "red"})
|
| 251 |
except Exception as e:
|
| 252 |
print(f"Command Error: {e}")
|
| 253 |
|
|
|
|
| 374 |
|
| 375 |
return jsonify({"status": "success", "id": loan_id})
|
| 376 |
|
| 377 |
+
return jsonify({"status": "success", "id": loan_id})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
|
| 379 |
@app.route('/repos')
|
| 380 |
@login_required
|
app/templates/prestamos.html
CHANGED
|
@@ -203,11 +203,6 @@
|
|
| 203 |
<p style="white-space:pre-wrap; font-size:0.9rem;">${loan.item}</p>
|
| 204 |
|
| 205 |
<div style="display:flex; gap:1rem; margin-top:1.5rem;">
|
| 206 |
-
${config.canDeliver ? `
|
| 207 |
-
<button class="btn" style="flex:1; background:#3b82f6; color:white;" onclick="entregarPrestamo('${loan.id}')">
|
| 208 |
-
<i class="fas fa-box"></i> ENTREGAR
|
| 209 |
-
</button>
|
| 210 |
-
` : ''}
|
| 211 |
<button class="btn btn-primary" style="flex:1;" onclick="closeModal()">Cerrar</button>
|
| 212 |
</div>
|
| 213 |
`;
|
|
@@ -215,21 +210,6 @@
|
|
| 215 |
overlay.style.display = 'block';
|
| 216 |
}
|
| 217 |
|
| 218 |
-
// Acción para marcar como entregado físicamente (Handover)
|
| 219 |
-
async function entregarPrestamo(loanId) {
|
| 220 |
-
if (!confirm('¿Confirmar la entrega de materiales?')) return;
|
| 221 |
-
|
| 222 |
-
const response = await fetch(`/api/entregar/${loanId}`, {
|
| 223 |
-
method: 'POST'
|
| 224 |
-
});
|
| 225 |
-
|
| 226 |
-
if (response.ok) {
|
| 227 |
-
location.reload();
|
| 228 |
-
} else {
|
| 229 |
-
alert('Error al procesar la entrega');
|
| 230 |
-
}
|
| 231 |
-
}
|
| 232 |
-
|
| 233 |
// Cerrar modal de recibo
|
| 234 |
function closeModal() {
|
| 235 |
document.getElementById('modal-content').style.display = 'none';
|
|
|
|
| 203 |
<p style="white-space:pre-wrap; font-size:0.9rem;">${loan.item}</p>
|
| 204 |
|
| 205 |
<div style="display:flex; gap:1rem; margin-top:1.5rem;">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
<button class="btn btn-primary" style="flex:1;" onclick="closeModal()">Cerrar</button>
|
| 207 |
</div>
|
| 208 |
`;
|
|
|
|
| 210 |
overlay.style.display = 'block';
|
| 211 |
}
|
| 212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
// Cerrar modal de recibo
|
| 214 |
function closeModal() {
|
| 215 |
document.getElementById('modal-content').style.display = 'none';
|