diff --git a/resources/views/renovaciones/contratos.html b/resources/views/renovaciones/contratos.html
index 84fa937..f2fe59f 100644
--- a/resources/views/renovaciones/contratos.html
+++ b/resources/views/renovaciones/contratos.html
@@ -116,6 +116,10 @@
+
+
@@ -572,6 +576,17 @@ document.addEventListener('alpine:init', () => {
} catch(e) { this.showToast(e.response?.data?.error||'Error', 'error'); }
},
+ async marcarPagado(d) {
+ if (!confirm(`¿Marcar el contrato de ${d.cliente?.nombre || '#'+d.ID} como pagado manualmente?\nEsto limpiará el enlace de Bold y renovará la fecha de vencimiento.`)) return;
+ try {
+ const { data } = await axios.post(`/app/api/contratos/${d.ID}/marcar-pagado`);
+ this.showToast(data.mensaje || 'Pago confirmado');
+ await this.loadData();
+ } catch(e) {
+ this.showToast(e.response?.data?.error || 'Error al marcar pago', 'error');
+ }
+ },
+
async verificarPago(d) {
this.verificandoID = d.ID;
try {
diff --git a/rest/controllers/contrato_controller.go b/rest/controllers/contrato_controller.go
index eebf9c9..640381a 100644
--- a/rest/controllers/contrato_controller.go
+++ b/rest/controllers/contrato_controller.go
@@ -442,3 +442,21 @@ func VerificarPagoBold(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"ok": true, "confirmado": true, "monto": monto, "mensaje": "¡Pago confirmado!"})
}
+
+// MarcarPagoManual confirma manualmente el pago de un contrato sin pasar por Bold.
+// POST /api/contratos/:id/marcar-pagado
+func MarcarPagoManual(c *fiber.Ctx) error {
+ id, err := strconv.ParseUint(c.Params("id"), 10, 64)
+ if err != nil {
+ return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
+ }
+ ok, err := models.MarcarContratoPagado(uint(id))
+ if err != nil {
+ return c.Status(500).JSON(fiber.Map{"error": err.Error()})
+ }
+ if !ok {
+ return c.JSON(fiber.Map{"ok": true, "mensaje": "El pago ya estaba confirmado"})
+ }
+ go services.EnviarCorreoConfirmacionPago(uint(id), "manual")
+ return c.JSON(fiber.Map{"ok": true, "mensaje": "Pago marcado como confirmado"})
+}
diff --git a/rest/routes/renovaciones.go b/rest/routes/renovaciones.go
index 4ec5c37..68a476b 100644
--- a/rest/routes/renovaciones.go
+++ b/rest/routes/renovaciones.go
@@ -40,6 +40,7 @@ func RenovacionesRoutes(protected fiber.Router) {
protected.Post("/api/contratos/:id/enviar-correo", controllers.EnviarCorreoContrato)
protected.Get("/api/contratos/:id/historial", controllers.GetHistorialContrato)
protected.Post("/api/contratos/:id/verificar-pago", controllers.VerificarPagoBold)
+ protected.Post("/api/contratos/:id/marcar-pagado", controllers.MarcarPagoManual)
// ─── Plantillas de correo ─────────────────────────────────────────
protected.Get("/plantillas-correo", middlewares.MenuMiddleware, controllers.PlantillasView)