Joyerías Meza — Sistema principal
Contexto
Sistema principal del cliente personal Joyerías Meza — punto de venta + administración general (ventas, inventarios, reportes). Cliente personal de Sergio, cliente grande de larga relación.
El sistema es ya un poco viejo. Sergio quiere modernizarlo a tecnologías más nuevas en un futuro no muy lejano (probable migración a Laravel reciente + Inertia/Vue, en línea con sus otros proyectos). Aún sin calendario.
Le piden cambios de vez en cuando — modo mantenimiento + features ocasionales.
Tareas pendientes
Comunicación con el cliente — paquete 2026 (tarifas + scope + Office)
Plan de fasear en 2 correos, separados ~4-6 semanas. Razonamiento completo en bitácora 2026-05-22 (entrada “Faseo de comunicación al cliente”). Drafts de los correos están redactados en esa bitácora.
- #178 📅 2026-06-02 — Redactar y enviar correo 1 al cliente (tarifa nueva + disponibilidad para trabajo grande + handoff profesional como opción abierta). Tarifa propuesta: $300 MXN/h desarrollo + $3,500 MXN/mes soporte, aplicación 1 de agosto de 2026. Draft listo en bitácora 2026-05-22; ajustar [Nombre] del contacto antes de enviar. Acción al confirmar recibo del cliente: actualizar
clients/joyerias-meza.mdcon la nueva tarifa vigente y marcarrate_locked_since: 2026-08. - #179 📅 2026-06-04 — Construir inventario actual de PCs + cuentas Office del cliente. Tabla en este mismo archivo o en
joyeriameza/inventario-pcs.md. Columnas: sucursal · etiqueta/nombre de la PC · usuario humano que la opera · cuenta Office instalada (una de las 3 familiares) · fecha de setup · estado (activa / fuera de uso / desconocida). Fuente principal: portal de admin de cada cuenta Office para ver dispositivos asociados. Pre-requisito del #181. - #180 📅 2026-06-06 — Documentar manual de setup de PC nueva (Office, bookmarks, startup apps, etc.) en formato paso a paso con screenshots, pensado para que cualquier persona de Joyerías Meza pueda seguirlo sin background técnico. Guardar en
joyeriameza/setup-pc-nueva.mdo equivalente. Pre-requisito del #181. - #181 📅 2026-06-08 — (bloqueado por #178 + #179 + #180) Redactar y enviar correo 2 al cliente: aclarar scope del soporte mensual (cubre software/fallas/ajustes; NO cubre hardware, configuración de PCs nuevas ni soporte de Office) + propuesta de handoff del proceso de setup de PCs y administración de las cuentas Office. Adjuntar inventario (#179) + link al manual (#180). Mandar 4-6 semanas después del correo 1, una vez digerida la tarifa. Draft listo en bitácora 2026-05-22.
Pendientes técnicos
- #372 (CERRADO 2026-05-27) Bug
limite_credito=0en cuentas de consignación fixeado, deployado y Veneza restaurada. Commite1d1abe(if ($total_pago > 0)envolviendo el bloque del cálculo del límite) pusheado por Sergio + deploy en prod. UPDATE manualcuentas_joyeria SET limite_credito = 4250 WHERE id = 9681aplicado por Sergio. Auditoría de otros clientes potencialmente afectados quedó sin ejecutar — capturar como follow-up si Sergio decide hacerla. - 📅 2026-06-10 — #373 (NUEVO 2026-05-27) Follow-up del bug compuesto: cuando se cancela una transacción que afectó al
limite_credito, el sistema no lo restaura (el método de cancelación no re-procesa el cálculo del límite). En el caso de Veneza, la transacción #1935290 fue cancelada 4 minutos después pero el límite ya estaba en 0 y se quedó así. Investigar el método de cancelación y agregar restauración del límite cuando se cancele una transacción de consignación que dejó saldo=0. Sin urgencia — el fix del #189 evita que el bug se repita; este follow-up es robustez adicional. - 📅 2026-06-15 — Plan de modernización (futuro, no calendarizado): definir alcance, costo, ventana, qué se migra y qué se reescribe. Nota: el correo 1 abre la puerta a este trabajo; si el cliente pica, abrir pendientes específicos aquí.
- 📅 2026-06-30 — Atender los pedidos de cambios conforme lleguen (irlos documentando aquí). Recordatorio: a partir del 1-ago-2026 cualquier desarrollo nuevo se cotiza a $300 MXN/h.
En progreso
(Mantenimiento on-demand.)
Notas técnicas
Stack actual (legado)
- PHP solo (composer.json detectado, sin package.json — sin frontend separado, probablemente Blade tradicional).
- Sin
ANTIGRAVITY.md. Versión exacta por confirmar concomposer.json.
Pendiente de documentar aquí
- Versión actual de Laravel/PHP.
- Setup de despliegue.
- Relación técnica con
jm-admin(DB compartida, auth, etc.). - Inventario de funcionalidades para el plan de modernización.
Bitácora
2026-05-27 — Bug del limite_credito = 0 en cuentas de consignación (commit e1d1abe local)
Reportó Viridiana González (admin de joyería):
“nos están reportando la cuenta de este cliente — ella liquida y carga el 14 de mayo pero cuando hace la devolución el día 13 de mayo le pone el límite en 0 — con un saldo de 600 pesos pero el límite se le queda en ceros y no la pueden cargar”
Screenshot mostraba al cliente Veneza Ivon Rascon Fuentes (id 7959): Límite $0, Saldo $600, Fecha límite 2026-05-29.
Investigación (autorizada SSH read-only por Sergio):
- BD prod confirmó
cuentas_joyeriaid=9681 (sistema_id=3 consignación) consaldo=600, limite_credito=0, fecha_limite=2026-05-29, lapso_fecha_limite="+15 day". - Tabla
transaccionesreveló cronología real del cliente entre 27-Apr y 23-May (10 transacciones), no entre 13-May como Viridiana mencionó. - Transacción culpable identificada: #1935290 del 2026-05-23 10:22:09 — devolución de $3,000 (sin pago) que dejó
saldo_anterior=3000 → saldo=0. Esa transacción fue CANCELADA 4 minutos después (10:26:46) con motivo “EP SE CAPTURO MAL”, pero ya había pisado el límite a 0 — y la cancelación NO restaura el límite (bug compuesto). - La transacción #1935326 del 10:58:24 fue la devolución “buena” ($2,400 que dejó saldo en $600), pero como
saldo ≠ 0ya no entró al bloque que recalcula límite y este siguió en 0.
Causa raíz en código — src/Controller/CuentasJoyeriaController.php:395-428:
if ($sistema->consignacion && $cuenta->saldo == 0 && !$cliente->bloqueado_por_atraso) {
$nuevoLimiteCredito = $cuenta->limite_credito;
if ($total_pago <= 0) {
$nuevoLimiteCredito = 0; // ← pisa el límite a 0 sin razón
} else {
// recálculo legítimo basado en pagoMayor × multiplo
}
$cuenta->limite_credito = $nuevoLimiteCredito;
}
Fix aplicado (commit e1d1abe, en local — push y deploy pendientes de Sergio):
- Agregada condición
$total_pago > 0al if exterior. - Removido el bloque if/else interno que pisaba a 0.
- Resultado: si no hubo pago en la transacción, el límite se queda intacto. Si hubo pago y saldo==0, recalcula con
pagoMayor × multiplocomo siempre.
Cálculo del límite correcto a restaurar a Veneza:
- Variables del sistema:
multiplo_limite_credito = 2,cantidad_ultimos_pagos = 4, min $3,000, max $40,000. - Último pago legítimo que recalculó el límite: $450 (2026-05-14 10:48:53, id #1929458).
ultimosPagos(true)en ese momento tomaba los 3 pagos anteriores: $2,125 + $100 + $1,225.pagoMayor = max($2,125, $100, $1,225, $450) = $2,125.nuevoLimite = $2,125 × 2 = $4,250(entre min 3k y max 40k).- →
UPDATE cuentas_joyeria SET limite_credito = 4250 WHERE id = 9681;
Auditoría sugerida para detectar otros clientes potencialmente afectados:
SELECT cj.id, cj.cliente_id, cj.saldo, cj.limite_credito
FROM cuentas_joyeria cj
JOIN sistemas s ON s.id = cj.sistema_id
WHERE s.consignacion = 1
AND cj.saldo > 0
AND cj.limite_credito = 0
LIMIT 100;
(filtrar también por clientes.bloqueado_por_atraso=0 si esa tabla está; clientes bloqueados sí esperan tener límite 0).
Pendientes (#372, #373):
- #372: ✅ CERRADO 2026-05-27 — commit
e1d1abepusheado + deployado + UPDATE manual a Veneza (limite_credito = 4250) aplicado por Sergio. Auditoría de otros clientes no se corrió — pendiente solo si Sergio decide hacerla. - #373 (sin urgencia): bug compuesto — cancelar transacción que afectó al límite no lo restaura.
2026-05-22 — Faseo de comunicación al cliente: tarifa + scope + handoff Office
Pidió Sergio: ayudarle a redactar mensaje al cliente para anunciar ajuste de tarifa (primer ajuste desde 2019), aclarar que el soporte mensual no cubre hardware ni setup de PCs, y proponer handoff del proceso de configuración de computadoras + administración de las cuentas Office (3 licencias familiares con 18 usuarios y hasta 5 PCs por usuario; sin inventario claro de qué cuenta está en qué PC).
Decisión: separar en 2 correos con ~4-6 semanas entre uno y otro.
Razonamiento del faseo:
- Mezclar todo en un correo se lee como “Sergio está renegociando todo y nos está dejando”. Faseado se lee como “Sergio está poniendo las cosas en orden”.
- Correo 1 (tarifa) va junto con el posicionamiento de relación (apertura a trabajo grande + handoff profesional si lo prefieren) porque eso le quita peso negativo al ajuste — se ve como mensaje sobre el futuro, no como recorte.
- Correo 2 (scope + Office) necesita trabajo previo del lado de Sergio: inventario de PCs/cuentas (#179) + manual de setup (#180). No se manda sin eso o suena a “ahora ustedes resuelven”.
Reglas que se aplicaron al redactar:
- No mencionar uso de IA (consistente con
clients/joyerias-meza.md > ai_disclosed: false). - No mencionar que Sergio tiene trabajo full-time (puede generar dudas sobre prioridad/atención — innecesario).
- Mantener tratamiento “usted” — más seguro al anunciar cambios de precio aunque la relación sea larga.
- Modernización del sistema: mencionar como disponibilidad, no como urgencia. Sergio no necesita vendérselo.
- Handoff: ofrecer como opción abierta, sin tono de “me quiero salir”.
- Antes de mandar: reemplazar
[Nombre]por el contacto real del cliente.
Draft — Correo 1 (mandar ahora, ~1-2 semanas)
Asunto: Actualización de tarifas y disponibilidad para 2026
Estimado [Nombre]:
Antes que nada, gracias por la confianza de todos estos años. La relación con Joyerías Meza ha sido una de las más sólidas que tengo, y eso lo aprecio mucho.
Quiero compartirle dos cosas que van relacionadas.
1. Ajuste de tarifas. Las tarifas que les he venido cobrando por desarrollo y soporte son las mismas que pactamos en 2019 — siete años sin ajuste. Considerando la inflación acumulada en México durante ese periodo (~35%) y el crecimiento del trabajo, que hoy abarca el sistema principal, el portal de administración, el checador y el módulo de contabilidad, es necesario actualizarlas:
Concepto Tarifa actual Tarifa nueva Hora de desarrollo $200 MXN $300 MXN Soporte mensual $2,500 MXN $3,500 MXN Este ajuste se mantiene por debajo de lo que cobro a clientes nuevos hoy, y refleja únicamente el costo de mantener el servicio actual con la calidad y disponibilidad a la que están acostumbrados.
Fecha de aplicación: 1 de agosto de 2026. Cualquier trabajo de desarrollo pendiente o en curso antes de esa fecha se cobra a la tarifa anterior; el soporte mensual de agosto en adelante ya entra con la nueva.
2. Disponibilidad para trabajo de fondo. En los últimos meses lo que les he atendido han sido principalmente requerimientos chicos. Hoy tengo disponibilidad y ganas de tomar también trabajo más grande: actualización/modernización del sistema (el codebase actual ya tiene tiempo y le toca un refresh técnico), nuevas funcionalidades, integraciones — lo que les sirva. Si tienen pendientes que han estado guardando porque “no quieren molestar”, este es buen momento para sacarlos. Cualquier proyecto grande se cotiza por separado, como siempre.
Por otro lado, también entiendo perfectamente si prefieren explorar otras opciones (otro proveedor, otra arquitectura, otra forma de trabajar). Si en algún momento es el caso, cuente con un handoff profesional: documentación, transferencia de accesos, soporte de transición. La relación que tenemos vale más que cualquier reacomodo, y mi prioridad es que el sistema siga funcionándoles bien tengan a quien tengan del otro lado.
Si quiere platicar de cualquiera de los dos puntos — o de ambos — quedo a sus órdenes. Si me confirma de recibido y conforme con el ajuste, perfecto también.
Un saludo, Sergio Valencia
Draft — Correo 2 (mandar 4-6 semanas después del 1, ya con #179 + #180 listos)
Asunto: Aclarando el scope del soporte y propuesta para el setup de equipos
Estimado [Nombre]:
Aprovechando que ya quedó arreglado lo de la tarifa, quiero poner en orden dos cosas que con el tiempo se han ido manejando informalmente y conviene formalizar:
1. Qué cubre el soporte mensual. El soporte de $3,500 MXN/mes cubre: fallas del sistema, ajustes menores, revisiones funcionales del software, disponibilidad para dudas. No cubre: revisión de hardware, configuración de computadoras nuevas, soporte de Office o cuentas de Microsoft, problemas de red o impresoras. Esos temas, cuando salgan, podemos verlos como trabajo puntual cobrado aparte, o ustedes los manejan internamente.
2. Setup de computadoras nuevas y cuentas de Office. Hasta ahora, cuando ustedes han comprado una PC nueva yo se las he configurado (Office, bookmarks, startup apps, etc.). Quiero pasarles el control completo de este proceso, porque hoy:
- No tengo un registro claro de cuál PC tiene cuál cuenta de Office activa.
- Ustedes dependen de mi tiempo para cualquier PC nueva, lo cual es un cuello de botella innecesario.
- Las 3 licencias familiares (18 usuarios, 5 PCs por usuario) son suyas, no mías; lo correcto es que ustedes las administren.
Propongo lo siguiente, ya con el trabajo preparado de mi lado:
- Inventario actual de PCs + cuentas: adjunto la tabla con lo que tenemos hoy mapeado. Si ven algo desactualizado, me dicen.
- Manual de setup paso a paso: [link al documento]. Cubre Office, bookmarks, startup, y los detalles que normalmente cuidaba yo.
- Handoff de las cuentas Office: les paso las credenciales y los passwords nuevos (yo ya no las uso). De ahí en adelante ustedes administran.
- Si en algún momento prefieren que yo configure una PC específica: con gusto, se cotiza como trabajo puntual (~1-2 horas por PC, $300-600 MXN según lo que pidan).
Si quieren platicar o ajustar algo, dígame. Si están de acuerdo, en cuanto reciba su confirmación les paso credenciales + manual.
Un saludo, Sergio
Notas operativas para el correo 2:
-
Antes de mandar, cambiar passwords de las 3 cuentas Office y guardarlos en el password manager del cliente (que ellos decidan cuál).
-
“Adjunto la tabla” = el inventario del #179.
-
“[link al documento]” = el manual del #180 (Google Doc compartido o equivalente).
-
Pidió Sergio: registrar el proyecto.
-
Hice: archivo creado. Capturada la intención de modernizar a stack más nuevo en el futuro.
-
Falta: documentar stack concreto + arrancar planeación de modernización cuando Sergio decida.
2026-05-12
- Pidió Sergio: resolver
Uncaught TypeError: anticiposVigentes.find is not a functional aplicar un anticipo en la vista de finalizar venta. - Diagnóstico (causa raíz):
- El controlador
CuentasJoyeriaController::ventaDevolucionarma$anticiposconarray_filter($cliente->anticipos_vigentes, fn => $a->sucursal_id === $usuario->sucursal_id). array_filterpreserva las llaves originales: si el cliente tiene anticipos en varias sucursales y se descarta uno intermedio, queda un array con llaves no consecutivas (ej.[0=>…, 2=>…]).json_encodeserializa ese array como objeto JSON ({"0":…,"2":…}), no como array ([…,…]).- El template
src/Template/Element/venta/div_informacion_venta.ctp:17lo escribe endata-anticipos, yjm.clientes.js:21lo lee con$('#informacion').data('anticipos')→ jQuery lo parsea como objeto. - En
jm.clientes.js:229,anticiposVigentes.find(...)falla porque los objetos no tienen.find(). - Sólo se reproduce cuando el cliente tiene anticipos vigentes en sucursales distintas a la del usuario logueado.
- El controlador
- Fix aplicado: envolver el
array_filterconarray_values(...)para reindexar las llaves antes de pasar al JSON.- Archivo:
src/Controller/CuentasJoyeriaController.php:109-111.
- Archivo:
- Fixes secundarios aplicados (autorizados por Sergio en la misma sesión):
webroot/js/jm.clientes.js:229-235— agregadoelse: si el id no aparece enanticiposVigentes,pagoAnticipose queda en 0 en lugar de explotar al leeranticipo.cantidad.src/Template/Element/venta/div_informacion_venta.ctp:17— el atributo ahora siempre serializa al menos[]:json_encode($anticipos ?? [], JSON_HEX_APOS|JSON_HEX_QUOT). Si en algún flujo el element se renderiza sin$anticipos, el JS sigue viendo un array vacío.
- Cache de assets: borré
tmp/cache/asset_compress/joyeria_meza.min.jspara que asset_compress regenere el bundle con el JS corregido en la siguiente request. - Commit & deploy:
5a0f4c9(“fix: corregir TypeError al aplicar anticipo en finalizar venta”) empujado aorigin/masteryservidor/master. El remotoservidorejecuta hook post-receive (se ven líneasremote: % Total ...típicas de curl en el deploy). - Validado en producción por Sergio el 2026-05-12. ✓