Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/corpentunida-org/corpen/llms.txt

Use this file to discover all available pages before exploring further.

The Portfolio module (/cartera) manages the cooperative’s accounts receivable. It provides three distinct capabilities: a delinquency list generated from an Excel upload (ReadExelController), a payment-proof (comprobante de pago) registration system where members upload evidence of their payments (CarComprobantePagoController), and a payment-agreement engine for restructuring delinquent debts (AcuerdoController). All routes are protected by the auth middleware. Payment vouchers uploaded in this module are the right-hand side of the reconciliation view in the Accounting module. Once an operator links a voucher to a bank transaction, the voucher’s estado transitions from pendiente to conciliado and is excluded from subsequent reconciliation passes.

Route reference

MethodURLRoute nameHandlerDescription
GET/carteracartera.morosos.indexReadExelController@indexPortfolio / delinquency list
POST/carteracartera.morosos.storeReadExelController@storeUpload Excel for delinquency processing
POST/cartera/pdfMoracartera.morosos.pdfMoraReadExelController@pdfMoraGenerate delinquency PDF
GET/cartera/comprobantescartera.comprobantes.indexCarComprobantePagoController@indexList payment vouchers
GET/cartera/comprobantes/createcartera.comprobantes.createCarComprobantePagoController@createNew voucher form
POST/cartera/comprobantescartera.comprobantes.storeCarComprobantePagoController@storeSubmit voucher (JSON response)
GET/cartera/comprobantes/{id}cartera.comprobantes.showCarComprobantePagoController@showView voucher
PUT/cartera/comprobantes/{id}cartera.comprobantes.updateCarComprobantePagoController@updateUpdate voucher
DELETE/cartera/comprobantes/{id}cartera.comprobantes.destroyCarComprobantePagoController@destroyDelete voucher and S3 file
GET/cartera/acuerdos(not yet registered)AcuerdoController@indexList agreements
GET/cartera/acuerdos/create(not yet registered)AcuerdoController@createNew agreement form
POST/cartera/acuerdos(not yet registered)AcuerdoController@storePersist agreement
GET/cartera/acuerdos/{id}(not yet registered)AcuerdoController@showAgreement detail
GET/cartera/acuerdos/{id}/edit(not yet registered)AcuerdoController@editEdit form
PUT/cartera/acuerdos/{id}(not yet registered)AcuerdoController@updateUpdate agreement
DELETE/cartera/acuerdos/{id}(not yet registered)AcuerdoController@destroyDelete agreement
The delinquency list routes (cartera.morosos.*) require the can:cartera.listamorosos.generarcarta permission in addition to authentication. Ensure users who need to view or process the receivables list have this permission assigned.

Payment vouchers (CarComprobantePago)

The car_comprobantes_pagos table stores each payment proof submitted by a member. The file itself is stored on Amazon S3 under the path corpentunida/cartera/comprobantes/{cod_ter_MaeTerceros}.

Key fields

FieldTypeNotes
cod_ter_MaeTercerosintegerPayer identifier (linked to MaeTerceros)
id_obligacioninteger (nullable)Obligation being paid
monto_pagadonumericAmount paid
fecha_pagonumeric (14 digits)Format YYYYMMDDHHMMSS — stored as a pure number
hash_transaccionstring (unique){id_banco}-{fecha_pago}-{monto_pagado}-{cod_ter_MaeTerceros}
ruta_archivostringS3 object key of the supporting file
id_bancointegerFK → con_cuentas_bancarias
numero_cuotainteger (nullable)Instalment number
tipo_pagostring (nullable, max 100)Payment method or category
observacionstring (nullable, max 255)Free-text note
estadoenumpendiente, conciliado, rechazado
id_userFK → usersUser who registered the voucher
The store action returns a JSON response rather than a redirect:
{ "success": true, "message": "Soporte almacenado correctamente." }
If the submitted hash already exists in the database, the controller responds with:
{
  "success": false,
  "is_duplicate": true,
  "message": "Ya existe un pago con estos mismos datos en este segundo exacto. ¿Deseas registrarlo de todas formas?"
}
The UI can then prompt the user to re-submit with the force_save: true flag, which appends -F-{timestamp} to the hash to satisfy the unique constraint while still persisting the record. When a voucher is deleted, the corresponding S3 object is also removed via Storage::disk('s3')->delete($comprobante->ruta_archivo).

User relationship

The User model exposes:
public function comprobantesRegistrados(): HasMany
{
    return $this->hasMany(CarComprobantePago::class, 'id_user');
}
This allows querying all vouchers submitted by a given user: $user->comprobantesRegistrados.

List view filters

The index action accepts the following query parameters:
ParameterEffect
periodoFilter by year-month (format Y-m). Default: current month
is_globalWhen present, removes the month filter (searches full history)
estadoFilter by voucher state (pendiente, conciliado, rechazado)
buscarFree text search across cod_ter_MaeTerceros, id_interaction, id_obligacion, monto_pagado, numero_cuota, pr, cco, tipo_pago, observacion, hash_transaccion, and id_transaccion_bancaria
The index paginates at 500 records per page to handle high-volume periods.

Payment agreements (Acuerdo)

Payment agreements (car_acuerdos) allow Corpen to formally restructure a delinquent obligation. Each agreement is linked to a specific credit in cre_creditos and captures the financial conditions frozen at the time of the agreement.

car_acuerdos schema

ColumnTypeNotes
idbigint (PK)Auto-increment
cre_creditos_idFK → cre_creditosDelinquent credit being restructured
numero_acuerdostring (unique)Agreement folio
fecha_acuerdodateDate the agreement was signed
estadoenumvigente, incumplido, pagado, cancelado
dias_mora_inicialintegerDays past due at the time of the agreement
intereses_corrientes_acuerdodecimal (15,2)Normal interest accrued
intereses_mora_acuerdodecimal (15,2)Penalty interest accrued
gastos_cobranzadecimal (15,2, nullable)Legal or collection costs included
user_idFK → users (nullable)Agent who managed the agreement
observacionestext (nullable)Special conditions or notes
The AcuerdoEstadoEnum PHP enum defines the valid states:
enum AcuerdoEstadoEnum: string
{
    case VIGENTE    = 'vigente';
    case INCUMPLIDO = 'incumplido';
    case PAGADO     = 'pagado';
    case CANCELADO  = 'cancelado';
}
The enum value for an active agreement is vigente, not activo. Always use vigente when creating or filtering agreements in their initial active state.
The User model exposes:
public function acuerdosRegistrados(): HasMany
{
    return $this->hasMany(Acuerdo::class, 'user_id');
}

Creating a payment agreement

1

Navigate to the agreement creation form

Go to GET /cartera/acuerdos/create. The form loads all credits from cre_creditos in a dropdown and the available agreement states via AcuerdoEstadoEnum::cases().
2

Select the delinquent credit

Choose the credit from the dropdown. This populates cre_creditos_id, which is the required foreign key linking the agreement to the member’s outstanding loan.
3

Set the agreement conditions

Complete the financial fields:
  • numero_acuerdo — a unique folio for the agreement (e.g. ACU-2025-001)
  • fecha_acuerdo — date the agreement was signed
  • dias_mora_inicial — current days past due
  • intereses_corrientes_acuerdo — accrued standard interest
  • intereses_mora_acuerdo — accrued penalty interest
  • gastos_cobranza — any legal costs being included (optional)
  • estado — initial state (vigente for new agreements)
  • observaciones — any special conditions
4

Submit and review

Submit POST /cartera/acuerdos. The StoreAcuerdoRequest Form Request validates the payload before the controller runs. The authenticated user’s ID is automatically injected as user_id. On success, you are redirected to acuerdos.index with the flash message: “Acuerdo creado exitosamente.”View the agreement at GET /cartera/acuerdos/{id} — the show action eager-loads both the parent credito and the usuario who created it.
A credit may accumulate multiple agreement records over its lifetime (e.g. an incumplido agreement followed by a new one). The database does not enforce a single-active-agreement constraint at the schema level, so business logic should verify the current agreement state before creating a new one.

Build docs developers (and LLMs) love