Skip to main content

Conceptos Clave

El módulo de Cuentas por Pagar gestiona:
  • Cuotas de compras a crédito generadas al registrar facturas de proveedores
  • Pagos completos (no soporta pagos parciales)
  • Estados de pago: 1 (pendiente), 0 (pagado)
  • Seguimiento de obligaciones por proveedor y documento
Diferencia clave con Cuentas por Cobrar: En Cuentas por Pagar NO se soportan pagos parciales. Al registrar un pago, la cuota completa se marca como pagada (estado = 0). Si necesita pagar parcialmente, debe dividir la compra en múltiples cuotas desde el inicio.

Flujo de Pago

1

Acceder al módulo de Cuentas por Pagar

Navegue a Finanzas → Cuentas por Pagar.Verá un resumen en tarjetas superiores:
  • Total Pendiente: Suma de monto de cuotas con estado = 1
  • Total Vencido: Suma de cuotas pendientes con fecha < hoy
  • Próximas a Vencer: Cantidad que vence en los próximos 7 días
  • Pagado este Mes: Total de cuotas pagadas en el mes actual
2

Filtrar las obligaciones

Use los filtros disponibles:

Por estado

  • Pendientes (estado=1): Cuotas no pagadas
  • Pagadas (estado=0): Cuotas ya saldadas
  • Vencidas (V): Pendientes con fecha < hoy

Por rango de fechas

  • Fecha desde / Fecha hasta: Filtra por fecha de vencimiento

Por proveedor

  • Busca por razon_social o ruc del proveedor
Los scopes del modelo DiaCompra.php automatizan los filtros:
public function scopePendientes($query) {
    return $query->where('estado', '1');
}

public function scopePagadas($query) {
    return $query->where('estado', '0');
}

public function scopeVencidas($query) {
    return $query->where('estado', '1')
                 ->where('fecha', '<', now());
}
3

Seleccionar la cuota a pagar

En la tabla, identifique la obligación mediante:
  • Documento: Serie-Número de la factura del proveedor (ej: F001-00003421)
  • Proveedor: Razón social y RUC
  • Fecha Emisión: Fecha de la compra
  • Fecha Vencimiento: Fecha límite de pago
  • Monto: Importe total a pagar (sin concepto de saldo)
  • Estado: Badge verde (Pagado) o rojo (Pendiente/Vencido)
Haga clic en el botón 💵 Pagar de la fila correspondiente.
4

Registrar el pago

Se abrirá el modal Registrar Pago mostrando:

Resumen de la obligación

Documento:          F001-00003421
Proveedor:          DISTRIBUIDORA NORTE SAC
RUC:                20123456789
Fecha Emisión:      2026-02-20
Fecha Vencimiento:  2026-03-20
Monto:              S/ 3,500.00

Formulario de pago

Fecha de pago (requerido)
  • Por defecto: fecha actual
  • Puede modificarla si el pago fue en otra fecha
No hay campo de monto: El sistema registra automáticamente el pago del monto completo de la cuota. No es posible pagar parcialmente.
5

Confirmar y actualizar estado

Al hacer clic en Registrar Pago, el sistema:
  1. Valida que no esté pagada:
    if ($cuota->estado === '0') {
        return response()->json([
            'success' => false,
            'message' => 'Esta cuota ya está pagada'
        ], 400);
    }
    
  2. Actualiza el registro en dias_compras:
    $cuota->estado = '0';  // Marca como pagada
    $cuota->fecha_pago = $request->fecha_pago;
    $cuota->save();
    
  3. Mensaje de confirmación: “Pago registrado exitosamente”

Estructura de Datos

Tabla: dias_compras

CampoTipoDescripción
dias_compra_idintegerID de la cuota
id_compraintegerFK a compras
fechadateFecha de vencimiento
montodecimal(10,2)Monto total a pagar
estadointeger1=Pendiente, 0=Pagado
fecha_pagodate (nullable)Fecha en que se pagó
Diferencias con dias_ventas (Cuentas por Cobrar):
  • No tiene campo numero_cuota (se asume cuota única)
  • No tiene monto_pagado ni saldo (solo pago completo)
  • No tiene observaciones
  • estado es integer (1/0) en lugar de string (‘P’/‘C’/‘V’)

Endpoint API

Consultar obligaciones

GET /api/cuentas-por-pagar?estado=1&fecha_desde=2026-03-01&proveedor=DISTRIBUIDORA
Authorization: Bearer {token}
Respuesta:
{
  "success": true,
  "data": [
    {
      "dias_compra_id": 87,
      "id_compra": 45,
      "documento": "F001-00003421",
      "proveedor": "DISTRIBUIDORA NORTE SAC",
      "proveedor_ruc": "20123456789",
      "fecha_emision": "2026-02-20",
      "fecha_vencimiento": "2026-03-20",
      "monto": "3500.00",
      "estado": "1",
      "fecha_pago": null
    }
  ],
  "resumen": {
    "total_pendiente": "67800.00",
    "total_vencido": "12500.00",
    "proximas_vencer": 5,
    "total_pagado_mes": "45600.00"
  }
}

Registrar pago

POST /api/cuentas-por-pagar/{dias_compra_id}/pagar
Authorization: Bearer {token}
Content-Type: application/json

{
  "fecha_pago": "2026-03-06"
}
Respuesta:
{
  "success": true,
  "message": "Pago registrado exitosamente"
}

Código del Controlador

En CuentasPorPagarController.php (línea 98-131):
public function pagar(Request $request, $id)
{
    $request->validate([
        'fecha_pago' => 'required|date',
    ]);
    
    $user = Auth::user();
    $cuota = DiaCompra::whereHas('compra', function ($q) use ($user) {
        $q->where('id_empresa', $user->id_empresa);
    })->findOrFail($id);
    
    if ($cuota->estado === '0') {
        return response()->json([
            'success' => false,
            'message' => 'Esta cuota ya está pagada'
        ], 400);
    }
    
    $cuota->estado = '0';
    $cuota->fecha_pago = $request->fecha_pago;
    $cuota->save();
    
    return response()->json([
        'success' => true,
        'message' => 'Pago registrado exitosamente',
    ]);
}

Cálculo de Resumen

En CuentasPorPagarController.php (línea 68-88):
$baseQuery = fn() => DiaCompra::whereHas('compra', function ($q) use ($idEmpresa) {
    $q->where('id_empresa', $idEmpresa)->where('estado', '1');
});

$totalPendiente = $baseQuery()->pendientes()->sum('monto');
$totalVencido = $baseQuery()->vencidas()->sum('monto');
$proximasVencer = $baseQuery()->proximasVencer(7)->count();
$totalPagadoMes = $baseQuery()->pagadas()
    ->whereMonth('fecha_pago', now()->month)
    ->whereYear('fecha_pago', now()->year)
    ->sum('monto');

Comparación con Cuentas por Cobrar

CaracterísticaCuentas por CobrarCuentas por Pagar
Tabladias_ventasdias_compras
Tipo de estadoString (‘P’,‘C’,‘V’)Integer (1, 0)
Pagos parciales✅ Permitidos❌ Solo completo
Campo saldo✅ Presente❌ No existe
Campo observaciones✅ Presente❌ No existe
Campo numero_cuota✅ Presente❌ No existe
Vencimientofecha_vencimientofecha

Flujo de Compra a Crédito

Cuando se registra una compra con tipo de pago a crédito:
  1. Se crea el registro en compras con id_tipo_pago != 1
  2. Se generan registros en dias_compras según el plan de pagos:
    • Compra de S/. 10,000 en 4 cuotas mensuales
    • Genera 4 registros con monto = 2500 cada uno
    • Fechas espaciadas según el intervalo (7, 15, 30 días, etc.)
// Ejemplo de generación de cuotas en ComprasController
foreach ($cuotas as $index => $cuota) {
    DiaCompra::create([
        'id_compra' => $compra->id_compra,
        'fecha' => $cuota['fecha'],
        'monto' => $cuota['monto'],
        'estado' => '1',  // Pendiente
    ]);
}

Integración con Caja

Los pagos a proveedores pueden registrarse como egresos de caja:
  1. Vaya a Finanzas → Caja (caja abierta)
  2. Registre un movimiento:
    • Tipo: Egreso
    • Concepto: “Pago a proveedor F001-00003421”
    • Monto: 3,500.00
  3. Luego registre el pago en Cuentas por Pagar
Esto mantiene el flujo de efectivo sincronizado.

Solución de Problemas

La cuota tiene estado = '0'. Verifique en la tabla si efectivamente fue pagada (fecha_pago presente). Si es un error, debe cambiarse manualmente:
UPDATE dias_compras 
SET estado = '1', fecha_pago = NULL 
WHERE dias_compra_id = 87;
El sistema actual NO soporta pagos parciales en Cuentas por Pagar. Opciones:
  1. Dividir la compra desde el inicio: Al registrar la compra, cree múltiples cuotas más pequeñas
  2. Workaround manual: Edite la base de datos para dividir el registro en dias_compras en dos filas con montos parciales
Se recomienda implementar la funcionalidad de pagos parciales en futuras versiones.
Debe editar manualmente la base de datos:
UPDATE dias_compras 
SET estado = '1', fecha_pago = NULL 
WHERE dias_compra_id = 87;
Se recomienda agregar un botón “Anular Pago” en la interfaz.
Verifique que la compra:
  1. Tenga id_tipo_pago != 1 (no sea al contado)
  2. Tenga registros en dias_compras
  3. Tenga estado = '1' en compras (no anulada)
Las compras al contado no generan obligaciones.

Reportes Relacionados

  • Reporte de Antigüedad de Deudas: Agrupa por días vencidos
  • Reporte por Proveedor: Total adeudado por proveedor
  • Historial de Pagos: Log de todos los pagos del mes

Mejoras Sugeridas

Funcionalidades que podrían agregarse:
  1. Soporte para pagos parciales (similar a Cuentas por Cobrar)
  2. Campo de observaciones por pago
  3. Botón de “Anular Pago” en la UI
  4. Número de cuota para mejor seguimiento
  5. Alertas automáticas de próximos vencimientos
  6. Integración directa con movimientos de caja/banco

Próximos Pasos

Build docs developers (and LLMs) love