Skip to content

Credit Line Requests UI

Frontend screens for the Credit Line Requests module, located under the Contabilidad menu group, and the DocuSign Credit Contracts configuration screen under the Legal menu group.

Architecture Overview

The frontend follows the standard admon pattern:

  • Views are under frontend/client/src/views/
  • Services extend the Base service class and call the admon backend
  • Routes are registered in frontend/client/src/routes/index.js
  • All services are registered as singletons in frontend/client/src/services/index.js

Files

frontend/client/src/
├── routes/index.js                                          # Added routes for both modules
├── services/
│   ├── credit-line-requests.service.js                     # API calls for request management
│   └── docusign-credit-contracts.service.js                # API calls for contract config
├── views/
│   ├── credit-line-requests/
│   │   ├── index.vue                                        # View shell (SectionTitle + Table)
│   │   ├── constants.js                                      # Status/contract enums + CREDIT_LINE_PAGARE_FIELD
│   │   └── components/
│   │       ├── Table.vue                                    # Main paginated table with filters + pagaré status badges
│   │       ├── CreditLineRequestDetail.vue                  # Container: fetches data + pagaré sub-flow actions
│   │       ├── CreditLineRequestInfo.vue                    # Request metadata display + pagaré file links
│   │       ├── CreditLineHistoryTab.vue                     # Credit line history accordion
│   │       └── CreditDocuments.vue                          # Document approval/rejection table (excludes pagaré docs)
│   └── docusign-credit-contracts/
│       ├── index.vue                                        # View shell
│       └── components/
│           ├── Table.vue                                    # DocuSign contracts list
│           └── ContractForm.offcanvas.vue                   # Create/edit form offcanvas
└── views/ticketsV2/components/
    └── Information.offcanvas.vue                            # Extended with #extra-sidebar slot

Screens

Credit Line Requests List

Route: /credit-line-requestsFile: views/credit-line-requests/index.vue + components/Table.vue

The main table shows all credit line requests with the following columns:

ColumnDescription
TicketFormatted as #XXXXX, linked to ticket
CompanyCompany name with country flag
Assigned ToLegal executive assigned to the ticket
Requested AmountAmount in local currency
Contract StatusColored badge: no_contract / sent / created / signed / manual
Request StatusColored badge: pending_commercial / approved_commercial / document_rejected / pagare_sent / pagare_review / pagare_validated / contract_sent / legal_review / active / rejected
SLADays since creation, color-coded: green (on time), yellow (delayed), red (overdue)
Actions"Ver info" button to open the detail offcanvas

Filter panel:

FilterInput Type
CompanyNumber input
StatusMulti-select (Select2)
Contract StatusMulti-select (Select2)
Date rangeDate picker

The Export CSV button triggers the DataTable streaming export via report=true query parameter.


Credit Line Request Detail (Offcanvas)

Component: views/ticketsV2/components/Information.offcanvas.vue (extended) Triggered by: "Ver info" in the table → informationOffcanvasRef.show(ticket_id, creditRequestId)

The standard Information.offcanvas.vue was extended backward-compatibly:

  • New prop hideRefundInfo (Boolean, default false): hides the three refund/transfer accordions. Set to true for credit line requests to avoid showing irrelevant refund data.
  • New extraId ref: passed to show(ticket_id, extraId) and exposed via the #extra-sidebar slot.
  • New scoped slot #extra-sidebar: renders CreditLineRequestDetail with props { ticket, loading, extraId }.
  • hide() resets extraId to null so each open fetches fresh data.

The offcanvas renders the ticket detail on the right column and the credit-specific content (via #extra-sidebar) at the bottom of the left column.


CreditLineRequestDetail (Container)

File: views/credit-line-requests/components/CreditLineRequestDetail.vue

This is a data container component:

  • Receives { ticket, loading, extraId } from the #extra-sidebar slot
  • Calls api.creditLineRequests.getRequestDetail(extraId) via watchEffect — re-fetches whenever extraId changes
  • Renders two Accordion blocks:
    1. Request InfoCreditLineRequestInfo
    2. DocumentsCreditDocuments
  • On @updated from CreditDocuments, re-fetches to reflect latest statuses

CreditLineRequestInfo

File: views/credit-line-requests/components/CreditLineRequestInfo.vue

Displays request metadata. No internal API calls — all data comes from the container.

Fields shown:

  • Requester (from linked ticket)
  • Requested amount and days
  • Approved amount and days (if set)
  • Request status badge
  • Contract status badge
  • Pagaré files (when present): a Download format link (pagare_format) and a View signed link (pagare_signed), rendered inline in the info table

CreditDocuments

File: views/credit-line-requests/components/CreditDocuments.vue

Compact 2-column table for reviewing submitted documents:

ColumnDescription
Documentdocument_name (bold); type=file shows "Ver archivo" link opening FilePreview.modal.vue; type=text shows raw value
Status (110px fixed)Status badge, optional rejection reason, Approve/Reject icon buttons

Approve flow: Swal confirmation → PATCH /credit-line-requests/{id}/documents/{documentId} with status: approved → emits updated.

Reject flow: Swal textarea prompt (required) → PATCH with status: rejected and rejection_reason → emits updated.

FilePreview.modal.vue is rendered via <Teleport to="body">.

Pagaré documents are excluded. The component computes visibleDocuments by filtering out pagare_format and pagare_signed (CREDIT_LINE_PAGARE_FIELD), so those are never shown in this generic list or counted by the bulk actions — they live in the dedicated pagaré section of CreditLineRequestDetail.

Permission gating. The approve/reject buttons and the bulk action bar are only rendered when the user has the credit-line-requests-review-documents permission (canReviewDocuments via useAuthStore().can(...)). The "Ver archivo" preview and file re-upload remain available without it.


Pagaré Sub-Flow (inside CreditLineRequestDetail)

File: views/credit-line-requests/components/CreditLineRequestDetail.vue

For Mexico (creditRequest.requires_pagare === true), CreditLineRequestDetail renders status-driven alert panels above the request accordions. Only one panel shows at a time, based on the request status:

Panel (computed flag)Shown whenContent / action
showDocumentRejectedNoticestatus document_rejectedWarning: a KYC/KYB document was rejected; waiting for the client to re-upload
showUploadPagareFormatstatus approved_commercial, requires pagaré, all required docs approved, not yet approved, has credit-line-requests-manageFile input + Upload pagaré format button → POST /pagare/format
showPagareSentWaitingstatus pagare_sentWarning: waiting for the client's signed upload + a link to download the uploaded format
showPagareReviewstatus pagare_review, has credit-line-requests-review-documentsLink to view the signed pagaré + Validate / Reject buttons → PATCH /pagare/validate

Computed helpers:

  • requiresPagarecreditRequest.requires_pagare
  • pagareFormatDoc / pagareSignedDoc ← documents matched by CREDIT_LINE_PAGARE_FIELD.FORMAT / .SIGNED
  • pagareApprovedpagareSignedDoc.status === 'approved'
  • requiredDocuments / allRequiredDocumentsApproved ← required, non-pagaré documents (an empty list counts as "all approved", mirroring the backend)

Upload format flow: select a PDF/DOC/DOCX → Swal confirm → uploadPagareFormat(id, formData) (multipart). On a 400 with pending_documents, a toast lists the still-pending documents.

Validate flow: Swal confirm → validatePagare(id, { status }). Approve advances to pagare_validated; reject returns to pagare_sent. After either action the detail is re-fetched and updated is emitted so the table row and offcanvas badge reflect the new status.

Contract gating. contractActionBase now allows the Create Contract action in approved_commercial or pagare_validated, and additionally requires pagareApproved when the country needs a pagaré — so for Mexico the contract button only appears once the signed pagaré is validated.


CreditLineHistoryTab

File: views/credit-line-requests/components/CreditLineHistoryTab.vue

Displays the company's credit line request history. Rendered as an additional accordion in CreditLineRequestDetail. Shows past requests with their statuses, amounts, and dates to give context when reviewing a new application.


DocuSign Credit Contracts Screen

Route: /docusign-credit-contractsMenu group: Legal

List (views/docusign-credit-contracts/index.vue + components/Table.vue)

Lists all registered DocuSign contract configurations. Columns:

ColumnDescription
NameFriendly name
CountryLocale flag + country name
Person Typekyb or kyc badge
Template IDDocuSign Template ID (truncated)
ActiveToggle badge
ActionsEdit button

Filters: locale, person type, active status.

Create / Edit Form (components/ContractForm.offcanvas.vue)

Offcanvas form with the following fields:

FieldTypeNotes
NameTextRequired
DescriptionTextareaOptional
DocuSign Template IDTextRequired — obtain from DocuSign Templates admin
CountrySelect (locales catalog)Required
Person TypeSelect (kyb / kyc)Required
ActiveToggleOnly one active per locale + person type

On create → POST /docusign-credit-contracts On edit → PATCH /docusign-credit-contracts/{id}

If activating a config when another is already active for the same locale + person type, the API will return 409 Conflict.


Services

CreditLineRequestsService

frontend/client/src/services/credit-line-requests.service.js

Extends Base with baseURL: process.env.ENVIA_ADMIN_API_HOSTNAME.

MethodHTTPEndpoint
getRequests(filters)GET/credit-line-requests
getRequestDetail(id)GET/credit-line-requests/{id}
getCreditLineHistory(id)GET/credit-line-requests/{id}/credit-line-history
updateRequestStatus(id, payload)PATCH/credit-line-requests/{id}/status
updateRequestDetails(id, payload)PATCH/credit-line-requests/{id}/details
updateDocumentStatus(requestId, documentId, payload)PATCH/credit-line-requests/{id}/documents/{documentId}
bulkUpdateDocumentStatus(id, payload)PATCH/credit-line-requests/{id}/documents/bulk
uploadPagareFormat(requestId, formData)POST/credit-line-requests/{id}/pagare/format (multipart)
validatePagare(requestId, payload)PATCH/credit-line-requests/{id}/pagare/validate
createContract(id)POST/credit-line-requests/{id}/contract
downloadDocuments(id)GET/credit-line-requests/{id}/documents/download
downloadSignedContract(id)GET/credit-line-requests/{id}/contract/signed-download
syncSignedContract(id)POST/credit-line-requests/{id}/contract/signed-storage-sync

DocusignCreditContractsService

frontend/client/src/services/docusign-credit-contracts.service.js

MethodHTTPEndpoint
getContracts(filters)GET/docusign-credit-contracts
create(payload)POST/docusign-credit-contracts
getById(id)GET/docusign-credit-contracts/{id}
update(id, payload)PATCH/docusign-credit-contracts/{id}

Component Extension: Information.offcanvas.vue

This shared component was modified in a fully backward-compatible manner. All existing consumers (tickets, overweights, etc.) are unaffected because:

  • hideRefundInfo defaults to false — existing accordions are shown by default
  • extraId is null by default — the #extra-sidebar slot renders nothing if not filled
  • show() signature change is additive (creditRequestId = null default)

Usage from CreditLineRequests Table:

vue
<InformationOffcanvas
  ref="informationOffcanvasRef"
  :hide-refund-info="true"
>
  <template #extra-sidebar="{ ticket, loading, extraId }">
    <CreditLineRequestDetail
      :ticket="ticket"
      :loading="loading"
      :extra-id="extraId"
    />
  </template>
</InformationOffcanvas>

i18n Keys

All i18n keys are loaded from S3 JSON files (es-MX.json / en-US.json). Keys added for this module are under the creditLineRequests.* and docusignCreditContracts.* namespaces. The full key list is available in openspec/changes/credit-line-requests/TRANSLATIONS.md.

The pagaré sub-flow adds keys under creditLineRequests.pagare.* (e.g. title, downloadFormat, viewSigned, uploadFormat.*, waiting.notice, review.notice, actions.validate/actions.reject, documentRejectedNotice) and new request-status labels under creditLineRequests.status.* (document_rejected, pagare_sent, pagare_review, pagare_validated, contract_sent).

The client-facing pagaré signing instructions posted to the ticket are hardcoded in Spanish (they reference Envia's Monterrey legal office and Mexican legal requirements), reflecting that the pagaré step is currently Mexico-only. Other automatic ticket comments (format sent, validated, rejected) use i18n keys (creditLineRequests.pagare.*) resolved in the company's language with an English fallback.

System-generated ticket comments (inserted on DocuSign webhook events) are resolved in the company's language using the Translator class and fall back to English if the translation key is not found.

Envia Admin