Skip to main content

Overview

The Transacciones API provides read-only access to transaction records in the POS system. Transactions are automatically created when invoices are approved or canceled, serving as an audit trail for inventory movements.
This is a read-only endpoint. Transactions are created automatically by the system during invoice approval and cancellation processes. Manual transaction creation is not supported through this API.

Authentication

Authorization: Bearer <your_jwt_token>
The JWT token must contain usuario and password fields for database connection credentials.

Get All Transactions

GET
endpoint
/api/pos/transaccion
Retrieves all transaction records from the system, ordered by description. This endpoint returns the complete transaction history.

Example Request

curl -X GET https://api.example.com/api/pos/transaccion \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response

Returns an array of transaction objects ordered by trn_descripcion.
trn_cod
string
Transaction code (auto-generated)
trn_descripcion
string
Transaction description (typically “Factura “)
200 Success
[
  {
    "trn_cod": "TRN0001",
    "trn_descripcion": "Factura FAC0001"
  },
  {
    "trn_cod": "TRN0002",
    "trn_descripcion": "Factura FAC0002"
  },
  {
    "trn_cod": "TRN0003",
    "trn_descripcion": "Factura FAC0005"
  }
]
404 Not Found
{
  "message": "No se encontraron transacciones"
}
500 Server Error
{
  "message": "Error retrieving transactions"
}

Transaction Records

What are Transactions?

Transactions (transaccion table) serve as a centralized record of all inventory-affecting operations in the POS system. Each transaction:
  • Has a unique auto-generated code (trn_cod)
  • Contains a description identifying the source operation
  • Links to kardex entries for detailed product movements
  • Provides an audit trail for inventory changes

When are Transactions Created?

Transactions are automatically created during:
  1. Invoice Approval - When an invoice transitions from PEN to APR status
    • Transaction type: Sale/Outbound
    • Description: “Factura
    • Creates kardex entries for each product with negative quantities (stock decrease)
  2. Invoice Cancellation - When an invoice is canceled (transitions to ANU status)
    • Transaction type: Reversal/Inbound
    • Description: “Anulación Factura
    • Creates kardex entries for each product with positive quantities (stock restore)

Transaction Lifecycle


Transaction Table Schema

The transaccion table stores transaction headers:
ColumnTypeDescription
trn_codVARCHARTransaction code (PK, auto-generated)
trn_tipoVARCHARTransaction type identifier
trn_descripcionVARCHARHuman-readable description
trn_fechaTIMESTAMPTransaction creation date

Kardex Integration

Each transaction is linked to multiple kardex entries (kardex_prd table):
ColumnTypeDescription
krd_codigoVARCHARKardex entry code (PK)
trn_codVARCHARTransaction reference (FK)
prd_codigoVARCHARProduct code (FK)
fac_codigoVARCHARInvoice reference (FK)
krd_cantidadINTEGERQuantity moved (negative for sales)
krd_razonVARCHARReason for movement
krd_fechahoraTIMESTAMPMovement timestamp
usr_idVARCHARUser who performed action

Use Cases

Audit Trail

Query transactions to track all inventory-affecting operations:
// Get all transactions
const transactions = await fetch('/api/pos/transaccion', {
  headers: { 'Authorization': 'Bearer TOKEN' }
}).then(r => r.json());

// Filter by invoice
const invoiceTransactions = transactions.filter(t => 
  t.trn_descripcion.includes('FAC0001')
);

Reconciliation

Use transaction records to reconcile inventory movements with invoice records:
  1. Retrieve all transactions
  2. Match transaction codes with kardex entries
  3. Verify stock changes align with invoice details
  4. Identify discrepancies or missing transactions

Reporting

Generate reports on system activity:
  • Volume Reports: Count transactions by date range
  • Invoice Tracing: Track which invoices generated transactions
  • Movement Analysis: Analyze transaction patterns over time

Limitations

The current API implementation has the following limitations:
  1. No Pagination: Returns all records. For large datasets, this may cause performance issues.
  2. No Filtering: Cannot filter by date, type, or invoice code.
  3. No Detailed Info: Only returns code and description. Full transaction details require additional queries.
  4. Read-Only: No POST, PUT, or DELETE operations supported.
For production use, consider implementing:
  • Pagination: Add page and limit query parameters
  • Date Filtering: Filter by trn_fecha date range
  • Invoice Lookup: Get transactions by invoice code
  • Type Filtering: Filter by transaction type
  • Detailed View: Include related kardex entries and stock changes
  • Search: Support description search
Example enhanced endpoint structure:
GET /api/pos/transaccion?page=1&limit=20&invoice=FAC0001&type=SALE&from=2024-03-01&to=2024-03-31

Error Handling

Common Error Responses

404 No Records Found
{
  "message": "No se encontraron transacciones"
}
This occurs when the transaccion table is empty. This is normal for new systems before any invoices have been approved.
500 Server Error
{
  "message": "Database connection error"
}
Indicates a database connection or query execution failure.
401 Unauthorized
{
  "message": "Token inválido o expirado"
}
Authentication token is missing, invalid, or expired.

Implementation Details

Source Code Reference

  • Route: src/routes/pos.transaccion.routes.js:8
  • Controller: src/controllers/pos.transaccion.controller.js:12-27
  • Model: src/models/transaccion.model.js:1-9

Database Query

The endpoint executes a simple SELECT query:
SELECT trn_cod, trn_descripcion 
FROM transaccion 
ORDER BY trn_descripcion

Connection Management

Uses JWT-based database credentials:
const connectFromJWT = (req) => {
  const { usuario, password } = req.user;
  return getConnectionWithCredentials(usuario, password);
};

const pool = connectFromJWT(req);
try {
  const result = await getAllQuery(pool);
  // ... handle response
} finally {
  await pool.end();
}
Each request:
  1. Extracts credentials from JWT token
  2. Creates a new database connection pool
  3. Executes the query
  4. Closes the connection pool (in finally block)

Integration Examples

Get Transaction History

async function getTransactionHistory() {
  try {
    const response = await fetch('https://api.example.com/api/pos/transaccion', {
      headers: {
        'Authorization': `Bearer ${authToken}`
      }
    });
    
    if (response.status === 404) {
      console.log('No transactions found - system is new');
      return [];
    }
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    const transactions = await response.json();
    return transactions;
    
  } catch (error) {
    console.error('Failed to fetch transactions:', error);
    throw error;
  }
}

Filter by Invoice Code

Since the API doesn’t support filtering, implement client-side filtering:
async function getInvoiceTransactions(facturaCodigo) {
  const allTransactions = await getTransactionHistory();
  
  return allTransactions.filter(transaction => 
    transaction.trn_descripcion.includes(facturaCodigo)
  );
}

// Usage
const fac0001Transactions = await getInvoiceTransactions('FAC0001');
console.log(`Found ${fac0001Transactions.length} transactions for FAC0001`);

Build Transaction Timeline

async function buildTransactionTimeline() {
  const transactions = await getTransactionHistory();
  
  // Group by invoice
  const byInvoice = transactions.reduce((acc, trn) => {
    const match = trn.trn_descripcion.match(/Factura (FAC\d+)/);
    if (match) {
      const facCode = match[1];
      if (!acc[facCode]) acc[facCode] = [];
      acc[facCode].push(trn);
    }
    return acc;
  }, {});
  
  return byInvoice;
}

// Usage
const timeline = await buildTransactionTimeline();
console.log('Transactions by invoice:', timeline);
/*
{
  'FAC0001': [
    { trn_cod: 'TRN0001', trn_descripcion: 'Factura FAC0001' }
  ],
  'FAC0002': [
    { trn_cod: 'TRN0002', trn_descripcion: 'Factura FAC0002' },
    { trn_cod: 'TRN0005', trn_descripcion: 'Anulación Factura FAC0002' }
  ]
}
*/

Transactions are created as a result of invoice operations. See related endpoints: For detailed inventory movements, you may need to query the kardex_prd table directly (not currently exposed via API).

Future Enhancements

Potential improvements for the Transacciones API:

1. Pagination Support

GET /api/pos/transaccion?page=1&limit=20

2. Date Range Filtering

GET /api/pos/transaccion?from=2024-03-01&to=2024-03-31

3. Transaction Details

GET /api/pos/transaccion/:trn_cod
// Returns transaction with kardex entries

4. Invoice Lookup

GET /api/pos/transaccion?invoice=FAC0001
// Returns all transactions for specific invoice

5. Transaction Statistics

GET /api/pos/transaccion/stats
// Returns count, date range, transaction types
These enhancements are not currently implemented. Contact the development team if you need these features for your integration.

Best Practices

1. Cache Transaction Data

Since transactions are immutable (never updated or deleted), cache the results:
let transactionCache = null;
let cacheTimestamp = null;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedTransactions() {
  const now = Date.now();
  
  if (!transactionCache || (now - cacheTimestamp) > CACHE_TTL) {
    transactionCache = await getTransactionHistory();
    cacheTimestamp = now;
  }
  
  return transactionCache;
}

2. Handle Empty State

New systems won’t have transactions until the first invoice is approved:
async function displayTransactions() {
  try {
    const transactions = await getTransactionHistory();
    
    if (transactions.length === 0) {
      showMessage('No hay transacciones todavía. Aprueba una factura para crear la primera transacción.');
      return;
    }
    
    renderTransactionTable(transactions);
    
  } catch (error) {
    if (error.status === 404) {
      showMessage('Sistema nuevo - sin transacciones');
    } else {
      showError('Error cargando transacciones');
    }
  }
}

3. Correlate with Invoices

Cross-reference transactions with invoice data:
async function getInvoiceWithTransactions(facCodigo) {
  const [invoice, allTransactions] = await Promise.all([
    fetch(`/api/pos/factura/${facCodigo}`).then(r => r.json()),
    getTransactionHistory()
  ]);
  
  const relatedTransactions = allTransactions.filter(trn =>
    trn.trn_descripcion.includes(facCodigo)
  );
  
  return {
    ...invoice,
    transactions: relatedTransactions
  };
}

4. Monitor Transaction Creation

Verify transactions are created after invoice operations:
async function approveInvoiceWithVerification(facCodigo) {
  // Get transaction count before
  const beforeTransactions = await getTransactionHistory();
  const beforeCount = beforeTransactions.length;
  
  // Approve invoice
  await fetch(`/api/pos/factura/${facCodigo}/aprobar`, {
    method: 'PUT',
    headers: { 'Authorization': `Bearer ${token}` }
  });
  
  // Verify transaction was created
  const afterTransactions = await getTransactionHistory();
  const afterCount = afterTransactions.length;
  
  if (afterCount !== beforeCount + 1) {
    console.warn('Transaction may not have been created!');
  }
  
  const newTransaction = afterTransactions.find(trn =>
    trn.trn_descripcion.includes(facCodigo) &&
    !beforeTransactions.find(bt => bt.trn_cod === trn.trn_cod)
  );
  
  return newTransaction;
}

Summary

The Transacciones endpoint provides read-only access to the transaction audit trail:
  • Purpose: Track inventory-affecting operations
  • Creation: Automatic during invoice approval/cancellation
  • Access: GET endpoint returning all records
  • Limitations: No filtering, pagination, or detailed views
  • Use Cases: Audit, reconciliation, reporting
For detailed inventory movements, kardex records provide the complete picture, while transactions serve as high-level operation markers.

Build docs developers (and LLMs) love