Hub

joyerias-meza

jm-contabilidad 🥶

active medium work
Creado
2026-05-14
Actualizado
2026-05-15
Directorios
  • /home/sergio/code/jm-contabilidad

Actividad en bitácora 2 días

jun
jul
ago
sep
oct
nov
dic
ene
feb
mar
abr
may
L
X
V
Menos
Más

JM Contabilidad — Sistema central de empleados, nóminas y gastos Joyerías Meza

Contexto

Sistema central de administración de Joyerías Meza (gastos, nóminas, comisiones, cobranza, empleados, sucursales). Hosteado en gastos.joyeriameza.com. Es el sistema más activo de la cadena JM y se conecta a las DBs de los otros proyectos JM como satélites.

Sergio lo clonó al hub el 2026-05-14 cuando analizaba el bug de Lidia en jm-checador — necesitaba mapear quién administra qué para proponer un fix permanente sensato.

Tareas pendientes

(Ninguna activa derivada de este análisis — ver jm-checador para acciones concretas.)

Bug conocido: pivot cobranzas_cortes_cobradores no se limpia al borrar un corte

El modelo CorteCobrador::boot() cascadea deleted a movimiento_caja y gasto, pero no toca el pivot. La migración 2018_09_17_133633_create_cobranzas_cortes_cobradores.php define corte_cobrador_id como unsignedInteger con ->index(), sin FK ni CASCADE. Al borrar un corte por UI, las filas del pivot quedan huérfanas (referencian un corte que ya no existe).

Fix permanente posible (no implementado, fuera de scope):

  • Opción A: agregar FK con ON DELETE CASCADE en migración nueva.
  • Opción B: en el event deleted del modelo, agregar $corteCobrador->cobranzas_cobradores()->detach() antes de manipular movimiento_caja/gasto.

Por ahora, cualquier borrado manual desde tinker debe limpiar el pivot a mano (ver bitácora 2026-05-15).

En progreso

(Nada activo aquí.)

Notas técnicas

Stack

  • Framework: Laravel (con Vue.js inline templates + Bootstrap).
  • PHP: 7.4 en producción.
  • Hosting: gastos.joyeriameza.com (Plesk, user jmeza).
  • Bare repo de deploy: ~/git/jm_contabilidad.

Remotes locales

origin      git@github.com:sevaor/jm-contabilidad.git
production  jmeza@gastos.joyeriameza.com:~/git/jm_contabilidad

Múltiples conexiones de DB (config/database.php)

  • mysql (default) — DB propia de contabilidad (empleados, nominas, gastos, sucursales, comisiones, …).
  • mysql_admin — DB de admin.joyeriameza.com, sistema legacy. Modelo EmpleadoAdmin apunta aquí. Solo se usó para migrar empleados (one-shot via JMMigrarEmplados).
  • checador (DB jmeza_checador en checador.joyeriameza.com) — accede a horas_checadas, checadas, horarios_empleadas, horarios_nomina, variables, usuarios. Modelos: ChecadaChecador, HoraChecadaChecador.
  • sistema_ventas — DB del POS (tienda en linea). Modelo: muchos *SistemaVentas. Se lee para comisiones.
  • tienda_en_linea, otras — para el sitio público.

Relación con jm-checador (clave para el bug de Lidia)

La tabla empleados es ÚNICA y vive aquí (en la DB de contabilidad). jm-checador no tiene tabla propia de empleados — se conecta a esta vía una conexión nombrada admin (su EmpleadosTable.php declara defaultConnectionName() { return 'admin'; }). Lo confirma también que jm-checador no tiene migración CreateEmpleados y que su modelo respeta deleted_at IS null (soft delete estilo Laravel).

Aspectojm-checador (CakePHP)jm-contabilidad (Laravel)
¿Tiene tabla empleados propia?No — usa conexión admin → esta DBSí, es la dueña
empleados.descansoLee y escribe vía connection adminTabla propia
Form que edita descansoSolo a superadmin (forma_empleados.ctp:15 lo envuelve en if($usuario->admin))No lo edita a nadie (empleados/forma.blade.php no lo incluye)
Otras tablas (checadas, horas_checadas, horarios_empleadas, …)En jmeza_checadorjm-contabilidad las lee vía connection checador

Conclusión: la fuente de verdad de descanso es esta DB (jm-contabilidad), pero los dos sistemas la editan/usan diferente:

  • jm-checador la lee/escribe pero solo expone el campo a superadmin global.
  • jm-contabilidad no la expone en su propio form de empleados.

El fix permanente puede vivir en cualquiera de los dos proyectos (o ambos). El fix corto (UPDATE) se hace contra esta DB.

Modelos que cruzan DBs

  • App\Empleado::horasTrabajadasSemanaNomina() → lee DB::connection('checador')->table('horas_checadas'). Es la única integración activa con el checador.
  • App\ChecadaChecador y App\HoraChecadaChecador declaran protected $connection = 'checador'. Solo lectura para reportes/nómina.

ANTIGRAVITY.md

No tiene. Proyecto Laravel pre-Boost; convenciones de boilerplate no aplican.

Bitácora

2026-05-14

  • Pidió Sergio: clonar y analizar antes de proponer fix permanente para el bug de Lidia en jm-checador.
  • Hice:
    • Cloné git@github.com:sevaor/jm-contabilidad.git en ~/code/jm-contabilidad.
    • Agregué remote production a jmeza@gastos.joyeriameza.com:~/git/jm_contabilidad.
    • Mapeé conexiones de DB y la relación con el checador.
    • Confirmé que el formulario de empleados aquí NO edita descanso ni horarios semanales, y que las dos tablas empleados están duplicadas sin sync entre BDs.
  • Conclusión que llevo a jm-checador: el fix permanente debe vivir en jm-checador (donde está la fuente de verdad de empleados.descanso para el bloqueo), no en jm-contabilidad, porque ahí ni siquiera se edita ese campo y no hay sync.

2026-05-15

  • Pidió Sergio (reenvío de admin Joyerías Meza): borrar corte de cobrador folio 707 del 13-mayo (no puede ella sola por UI).
  • Diagnóstico:
    • “Folio” en UI = cortes_cobradores.id (resources/views/cortes_cobradores/show.blade.php:21). 707 = id 707.
    • Corte 707: 2026-05-13 09:08, cobrador “Jorge de la Rosa” (id 3), creado por cajera (usuario id 4), comisiones $310. Asociados: gasto id 15801 ($310 categoría Cobranza), sin movimiento_caja, 6 filas en pivot cobranzas_cortes_cobradores.
    • Policy CorteCobradorPolicy::eliminar exige tres condiciones: permiso_cobranza, usuario_id match, ser el último corte del cobrador. La admin tenía 1/3 (permiso) pero fallaba en las otras dos: no lo creó ella, y existe el corte 708 posterior (09:20 mismo día, mismo cobrador).
    • Lectura del incidente: la cajera creó 707, vio que metió la cobranza_cobrador #8 en vez de la #7, creó 708 para corregir. La cobranza_cobrador #10 quedó duplicada en ambos cortes → $310 contado dos veces como gasto. Borrar 707 deshace el duplicado y libera la #8.
  • Hice (tinker prod, transacción atómica):
    • Snapshot JSON del corte + pivot + gasto en jmeza:/tmp/corte_707_backup_20260515_152134.json.
    • DELETE FROM cobranzas_cortes_cobradores WHERE corte_cobrador_id=707 (6 filas — el event deleted del modelo no limpia el pivot, ver “Bug conocido” arriba).
    • CorteCobrador::find(707)->delete() → cascadea y borra gasto 15801.
  • Verificación: corte 707 ya no existe, gasto 15801 ya no existe, 0 filas restantes en pivot para corte 707, sin movimiento_caja huérfano. Cortes recientes del cobrador 3 ahora arrancan en 708 correctamente.