Puntos de Emisión
Puntos de Emisión
Section titled “Puntos de Emisión”Dominio: https://test-api-factura.edw-dev.com
Dominio: https://api-financiero.e-dinky.com
Esta sección documenta los endpoints relacionados con la gestión de puntos de emisión, incluyendo creación, consulta y eliminación de puntos de emisión para establecimientos empresariales.
Índice de Endpoints Disponibles
Section titled “Índice de Endpoints Disponibles”Consultas Empresariales
Section titled “Consultas Empresariales”- Consultar Puntos de Emisión - Listado de puntos de emisión por establecimiento
- Crear Punto de Emisión - Creación de nuevos puntos de emisión
- Eliminar Punto de Emisión - Eliminación de puntos de emisión
Consultas Administrativas
Section titled “Consultas Administrativas”- Consultar Puntos de Emisión (Admin) - Consulta administrativa con secuenciales
Consultar Puntos de Emisión
Section titled “Consultar Puntos de Emisión”Información General
Section titled “Información General”- Endpoint:
GET /api/v1/companies/emission-points/:accountId/:establishmentNo
- Método: GET
- Autenticación: Bearer Token requerido
- Descripción: Obtiene la lista de puntos de emisión para un establecimiento específico
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Accept: application/json
Parámetros de URL
Section titled “Parámetros de URL”Parámetro | Tipo | Requerido | Descripción |
---|---|---|---|
accountId | string | Sí | ID de la cuenta empresarial |
establishmentNo | string | Sí | Número del establecimiento (ej: “001”) |
Parámetros de Query (Opcionales)
Section titled “Parámetros de Query (Opcionales)”Parámetro | Tipo | Descripción |
---|---|---|
page | integer | Número de página para paginación (default: 1) |
limit | integer | Cantidad de registros por página (default: 10) |
status | string | Filtrar por estado: “active”, “inactive” |
search | string | Búsqueda por nombre o código |
Ejemplo de Request
Section titled “Ejemplo de Request”GET /api/v1/companies/emission-points/61247344/001?page=1&limit=10Authorization: Bearer {token}Accept: application/json
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Puntos de emisión obtenidos exitosamente", "status": "SUCCESS", "payload": { "current_page": 1, "data": [ { "id": 1, "emission_point_code": "001", "name": "Caja Principal", "description": "Punto de emisión principal del establecimiento", "establishment_code": "001", "establishment_name": "Matriz Principal", "status": "active", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "last_sequence_number": 1250, "document_types": [ "factura", "nota_credito", "nota_debito", "comprobante_retencion" ] }, { "id": 2, "emission_point_code": "002", "name": "Caja Secundaria", "description": "Punto de emisión secundario", "establishment_code": "001", "establishment_name": "Matriz Principal", "status": "active", "created_at": "2024-01-15T11:00:00Z", "updated_at": "2024-01-15T11:00:00Z", "last_sequence_number": 856, "document_types": [ "factura", "nota_credito" ] } ], "first_page_url": "http://api.example.com/api/v1/companies/emission-points/61247344/001?page=1", "from": 1, "last_page": 1, "last_page_url": "http://api.example.com/api/v1/companies/emission-points/61247344/001?page=1", "next_page_url": null, "path": "http://api.example.com/api/v1/companies/emission-points/61247344/001", "per_page": 10, "prev_page_url": null, "to": 2, "total": 2 }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X GET \ "{{apiFacEcDev}}/api/v1/companies/emission-points/61247344/001?page=1" \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->get($apiUrl . '/api/v1/companies/emission-points/' . $accountId . '/' . $establishmentNo, [ 'page' => 1, 'limit' => 10, 'status' => 'active']);
$emissionPoints = $response->json();
const axios = require('axios');
const getEmissionPoints = async (accountId, establishmentNo, options = {}) => { try { const params = new URLSearchParams({ page: options.page || 1, limit: options.limit || 10, ...(options.status && { status: options.status }), ...(options.search && { search: options.search }) });
const response = await axios.get( `${apiUrl}/api/v1/companies/emission-points/${accountId}/${establishmentNo}?${params}`, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Accept': 'application/json' } } );
console.log('Puntos de emisión:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Crear Punto de Emisión
Section titled “Crear Punto de Emisión”Información General
Section titled “Información General”- Endpoint:
POST /api/v1/companies/create-emission-points
- Método: POST
- Autenticación: Bearer Token requerido
- Descripción: Crea un nuevo punto de emisión para un establecimiento
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Content-Type: application/jsonAccept: application/json
Parámetros del Request Body
Section titled “Parámetros del Request Body”Campo | Tipo | Requerido | Descripción |
---|---|---|---|
account_id | string | Sí | ID de la cuenta empresarial |
establishment_code | string | Sí | Código del establecimiento (ej: “001”) |
emission_point_code | string | Sí | Código del punto de emisión (ej: “001”) |
name | string | Sí | Nombre descriptivo del punto de emisión |
description | string | No | Descripción detallada del punto |
document_types | array | No | Tipos de documentos permitidos |
initial_sequence | integer | No | Número de secuencia inicial (default: 1) |
status | string | No | Estado inicial: “active” o “inactive” (default: “active”) |
Tipos de Documentos Disponibles
Section titled “Tipos de Documentos Disponibles”factura
- Facturasnota_credito
- Notas de Créditonota_debito
- Notas de Débitocomprobante_retencion
- Comprobantes de Retenciónguia_remision
- Guías de Remisiónliquidacion_compra
- Liquidaciones de Compra
Ejemplo de Request
Section titled “Ejemplo de Request”{ "account_id": "61247344", "establishment_code": "001", "emission_point_code": "003", "name": "Caja Express", "description": "Punto de emisión para ventas rápidas", "document_types": [ "factura", "nota_credito", "nota_debito" ], "initial_sequence": 1, "status": "active"}
Respuesta Exitosa (201 Created)
Section titled “Respuesta Exitosa (201 Created)”{ "message": "Punto de emisión creado exitosamente", "status": "CREATED", "payload": { "id": 3, "emission_point_code": "003", "name": "Caja Express", "description": "Punto de emisión para ventas rápidas", "establishment_code": "001", "establishment_name": "Matriz Principal", "account_id": "61247344", "status": "active", "initial_sequence": 1, "current_sequence": 1, "document_types": [ "factura", "nota_credito", "nota_debito" ], "created_at": "2024-01-15T12:00:00Z", "updated_at": "2024-01-15T12:00:00Z" }}
Respuesta de Error (422 Unprocessable Content)
Section titled “Respuesta de Error (422 Unprocessable Content)”{ "message": "Error de validación", "status": "ERROR", "payload": null, "error": { "emission_point_code": [ "El código de punto de emisión ya existe para este establecimiento" ], "establishment_code": [ "El establecimiento no existe" ] }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X POST \ {{apiFacEcDev}}/api/v1/companies/create-emission-points \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}' \ -H 'Content-Type: application/json' \ -d '{ "account_id": "61247344", "establishment_code": "001", "emission_point_code": "003", "name": "Caja Express", "description": "Punto de emisión para ventas rápidas", "document_types": ["factura", "nota_credito", "nota_debito"]}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->post($apiUrl . '/api/v1/companies/create-emission-points', [ 'account_id' => '61247344', 'establishment_code' => '001', 'emission_point_code' => '003', 'name' => 'Caja Express', 'description' => 'Punto de emisión para ventas rápidas', 'document_types' => ['factura', 'nota_credito', 'nota_debito'], 'initial_sequence' => 1, 'status' => 'active']);
$newEmissionPoint = $response->json();
const axios = require('axios');
const createEmissionPoint = async (emissionPointData) => { try { const response = await axios.post( `${apiUrl}/api/v1/companies/create-emission-points`, emissionPointData, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } } );
console.log('Punto de emisión creado:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Eliminar Punto de Emisión
Section titled “Eliminar Punto de Emisión”Información General
Section titled “Información General”- Endpoint:
DELETE /api/v1/companies/delete-emission-points/:accountId/:establishmentNo/:emissionPoint
- Método: DELETE
- Autenticación: Bearer Token requerido
- Descripción: Elimina un punto de emisión específico
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Accept: application/json
Parámetros de URL
Section titled “Parámetros de URL”Parámetro | Tipo | Requerido | Descripción |
---|---|---|---|
accountId | string | Sí | ID de la cuenta empresarial |
establishmentNo | string | Sí | Número del establecimiento |
emissionPoint | string | Sí | Código del punto de emisión a eliminar |
Ejemplo de Request
Section titled “Ejemplo de Request”DELETE /api/v1/companies/delete-emission-points/61247344/001/003Authorization: Bearer {token}Accept: application/json
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Punto de emisión eliminado exitosamente", "status": "DELETED", "payload": { "account_id": "61247344", "establishment_code": "001", "emission_point_code": "003", "deleted_at": "2024-01-15T12:30:00Z", "final_sequence_number": 125, "documents_issued": 124 }}
Respuesta de Error (409 Conflict)
Section titled “Respuesta de Error (409 Conflict)”{ "message": "No se puede eliminar el punto de emisión", "status": "ERROR", "payload": null, "error": { "emission_point": [ "El punto de emisión tiene documentos pendientes de autorización" ] }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X DELETE \ {{apiFacEcDev}}/api/v1/companies/delete-emission-points/61247344/001/003 \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->delete($apiUrl . '/api/v1/companies/delete-emission-points/' . $accountId . '/' . $establishmentNo . '/' . $emissionPointCode);
$deleteResult = $response->json();
const axios = require('axios');
const deleteEmissionPoint = async (accountId, establishmentNo, emissionPointCode) => { try { const response = await axios.delete( `${apiUrl}/api/v1/companies/delete-emission-points/${accountId}/${establishmentNo}/${emissionPointCode}`, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Accept': 'application/json' } } );
console.log('Punto de emisión eliminado:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Validaciones y Reglas de Negocio
Section titled “Validaciones y Reglas de Negocio”Validación de Códigos
Section titled “Validación de Códigos”const validateEmissionPointCode = (code) => { // Debe ser exactamente 3 dígitos if (!/^\d{3}$/.test(code)) { throw new Error('El código debe tener exactamente 3 dígitos'); }
// No puede ser 000 if (code === '000') { throw new Error('El código 000 no es válido'); }
return true;};
const validateDocumentTypes = (types) => { const validTypes = [ 'factura', 'nota_credito', 'nota_debito', 'comprobante_retencion', 'guia_remision', 'liquidacion_compra' ];
const invalidTypes = types.filter(type => !validTypes.includes(type));
if (invalidTypes.length > 0) { throw new Error(`Tipos de documento inválidos: ${invalidTypes.join(', ')}`); }
return true;};
Gestión de Secuencias
Section titled “Gestión de Secuencias”class EmissionPointSequence{ public function getNextSequence($accountId, $establishmentCode, $emissionPointCode, $documentType) { $emissionPoint = $this->findEmissionPoint($accountId, $establishmentCode, $emissionPointCode);
if (!$emissionPoint) { throw new Exception('Punto de emisión no encontrado'); }
if (!in_array($documentType, $emissionPoint->document_types)) { throw new Exception('Tipo de documento no permitido en este punto de emisión'); }
// Obtener siguiente número de secuencia $nextSequence = $this->incrementSequence($emissionPoint, $documentType);
return str_pad($nextSequence, 9, '0', STR_PAD_LEFT); }
private function incrementSequence($emissionPoint, $documentType) { // Implementar lógica de incremento atómico return DB::transaction(function () use ($emissionPoint, $documentType) { $current = $emissionPoint->sequences()->where('document_type', $documentType)->first();
if (!$current) { $current = $emissionPoint->sequences()->create([ 'document_type' => $documentType, 'current_number' => 1 ]); } else { $current->increment('current_number'); }
return $current->current_number; }); }}
Códigos de Respuesta
Section titled “Códigos de Respuesta”- 200 OK: Consulta o eliminación exitosa
- 201 Created: Punto de emisión creado exitosamente
- 400 Bad Request: Parámetros inválidos
- 401 Unauthorized: Token de autorización inválido
- 404 Not Found: Recurso no encontrado
- 409 Conflict: Conflicto al eliminar (documentos pendientes)
- 422 Unprocessable Entity: Error de validación
- 500 Internal Server Error: Error interno del servidor
Mejores Prácticas
Section titled “Mejores Prácticas”🔢 Gestión de Secuencias
Section titled “🔢 Gestión de Secuencias”- Use transacciones para incrementos atómicos
- Implemente bloqueos para evitar duplicados
- Mantenga respaldos de secuencias críticas
- Monitoree saltos en numeración
🔐 Seguridad
Section titled “🔐 Seguridad”- Valide permisos antes de crear/eliminar puntos
- Registre todas las operaciones para auditoría
- Use validación estricta de códigos
- Implemente rate limiting
⚡ Rendimiento
Section titled “⚡ Rendimiento”- Use caché para consultas frecuentes
- Implemente paginación eficiente
- Optimice consultas de secuencias
- Considere índices en campos de búsqueda
📊 Monitoreo
Section titled “📊 Monitoreo”- Monitoree uso por punto de emisión
- Registre métricas de rendimiento
- Implemente alertas para errores
- Mantenga estadísticas de documentos emitidos
Casos de Uso Específicos
Section titled “Casos de Uso Específicos”📋 Configuración Inicial de Establecimiento
Section titled “📋 Configuración Inicial de Establecimiento”const setupEstablishmentEmissionPoints = async (accountId, establishmentCode) => { const defaultPoints = [ { code: '001', name: 'Caja Principal', description: 'Punto de emisión principal', documentTypes: ['factura', 'nota_credito', 'nota_debito', 'comprobante_retencion'] }, { code: '002', name: 'Caja Secundaria', description: 'Punto de emisión secundario', documentTypes: ['factura', 'nota_credito'] } ];
const results = [];
for (const point of defaultPoints) { try { const result = await createEmissionPoint({ account_id: accountId, establishment_code: establishmentCode, emission_point_code: point.code, name: point.name, description: point.description, document_types: point.documentTypes });
results.push({ success: true, point: point.code, data: result }); } catch (error) { results.push({ success: false, point: point.code, error: error.message }); } }
return results;};
🔄 Migración de Puntos de Emisión
Section titled “🔄 Migración de Puntos de Emisión”class EmissionPointMigration{ public function migrateFromLegacySystem($accountId, $legacyData) { $migrationResults = [];
foreach ($legacyData as $legacyPoint) { try { // Mapear datos del sistema legacy $mappedData = $this->mapLegacyData($legacyPoint);
// Crear punto de emisión $result = $this->createEmissionPoint([ 'account_id' => $accountId, 'establishment_code' => $mappedData['establishment_code'], 'emission_point_code' => $mappedData['emission_point_code'], 'name' => $mappedData['name'], 'description' => $mappedData['description'], 'document_types' => $mappedData['document_types'], 'initial_sequence' => $mappedData['last_sequence'] + 1 ]);
$migrationResults[] = [ 'success' => true, 'legacy_id' => $legacyPoint['id'], 'new_id' => $result['payload']['id'] ];
Log::info("Punto de emisión migrado: {$legacyPoint['id']} -> {$result['payload']['id']}");
} catch (Exception $e) { $migrationResults[] = [ 'success' => false, 'legacy_id' => $legacyPoint['id'], 'error' => $e->getMessage() ];
Log::error("Error migrando punto {$legacyPoint['id']}: {$e->getMessage()}"); } }
return $migrationResults; }}
Consultar Puntos de Emisión (Admin)
Section titled “Consultar Puntos de Emisión (Admin)”Información General
Section titled “Información General”- Endpoint:
GET /api/v1/admin/companies/accounts/establishments/emission-points/:companyId/:accountId/:establishmentNo
- Método: GET
- Autenticación: Bearer Token requerido
- Descripción: Endpoint administrativo para consultar puntos de emisión con información detallada de secuenciales
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Accept: application/json
Parámetros de URL
Section titled “Parámetros de URL”Parámetro | Tipo | Requerido | Descripción |
---|---|---|---|
companyId | string | Sí | ID de la empresa (RUC) |
accountId | string | Sí | ID de la cuenta empresarial |
establishmentNo | string | Sí | Número del establecimiento (ej: “001”) |
Ejemplo de Request
Section titled “Ejemplo de Request”GET /api/v1/admin/companies/accounts/establishments/emission-points/1359194914/509636719/001Authorization: Bearer {token}Accept: application/json
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Lista de valores", "status": "OK", "payload": { "items": [ { "pto_emision": "004", "establishment": "001", "sequentials": [ { "title": "Factura", "environment": "TEST", "next_number": 54, "sequential": "000000053", "code_doc": "01", "pto_emi": "004", "establishment_no": "001" }, { "title": "Nota de crédito", "environment": "TEST", "next_number": 7, "sequential": "000000006", "code_doc": "04", "pto_emi": "004", "establishment_no": "001" }, { "title": "Nota de débito", "environment": "TEST", "next_number": 9, "sequential": "000000008", "code_doc": "05", "pto_emi": "004", "establishment_no": "001" }, { "title": "Guía de remisión", "environment": "TEST", "next_number": 2, "sequential": "000000001", "code_doc": "06", "pto_emi": "004", "establishment_no": "001" }, { "title": "Comprobante de retención", "environment": "TEST", "next_number": 5, "sequential": "000000004", "code_doc": "07", "pto_emi": "004", "establishment_no": "001" }, { "title": "Liquidación de compras", "environment": null, "next_number": 1, "sequential": "000000000", "code_doc": "03", "pto_emi": "004", "establishment_no": "001" } ] } ], "count_items": 1, "current_page": 1, "number_paginate": 25, "last_page": 1 }}
Respuesta de Error (404 Not Found)
Section titled “Respuesta de Error (404 Not Found)”{ "message": "La cuenta no existe", "status": "ERROR", "payload": null, "error": "La cuenta no existe"}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X GET \ {{apiFacEcDev}}/api/v1/admin/companies/accounts/establishments/emission-points/1359194914/509636719/001 \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->get("{{apiFacEcDev}}/api/v1/admin/companies/accounts/establishments/emission-points/{$companyId}/{$accountId}/{$establishmentNo}");
$emissionPoints = $response->json();
const getAdminEmissionPoints = async (companyId, accountId, establishmentNo) => { try { const response = await fetch(`{{apiFacEcDev}}/api/v1/admin/companies/accounts/establishments/emission-points/${companyId}/${accountId}/${establishmentNo}`, { method: 'GET', headers: { 'Authorization': `Bearer ${bearerToken}`, 'Accept': 'application/json' } });
const data = await response.json(); return data; } catch (error) { console.error('Error:', error); }};
Información de Secuenciales
Section titled “Información de Secuenciales”Este endpoint proporciona información detallada sobre los secuenciales de cada tipo de documento:
Campos de Secuenciales
Section titled “Campos de Secuenciales”Campo | Descripción |
---|---|
title | Nombre del tipo de documento |
environment | Ambiente (TEST/PRODUCCIÓN) |
next_number | Próximo número a usar |
sequential | Secuencial actual formateado |
code_doc | Código SRI del documento |
pto_emi | Código del punto de emisión |
establishment_no | Número del establecimiento |
Códigos de Documentos SRI
Section titled “Códigos de Documentos SRI”Código | Tipo de Documento |
---|---|
01 | Factura |
03 | Liquidación de compras |
04 | Nota de crédito |
05 | Nota de débito |
06 | Guía de remisión |
07 | Comprobante de retención |
Casos de Uso
Section titled “Casos de Uso”🔧 Administración de Secuenciales
Section titled “🔧 Administración de Secuenciales”- Monitoreo de secuencias por punto de emisión
- Verificación de configuraciones de documentos
- Auditoría de numeración
📊 Reportes Administrativos
Section titled “📊 Reportes Administrativos”- Análisis de uso por tipo de documento
- Estadísticas de emisión por establecimiento
- Control de ambientes (TEST vs PRODUCCIÓN)
Notas Importantes
Section titled “Notas Importantes”- Permisos: Requiere permisos administrativos
- Secuenciales: Muestra información detallada de numeración
- Ambientes: Distingue entre TEST y PRODUCCIÓN
- Formato: Los secuenciales se muestran con formato de 9 dígitos
- Estados: Solo muestra puntos de emisión activos
Notas Importantes
Section titled “Notas Importantes”- Códigos Únicos: Los códigos de puntos de emisión deben ser únicos por establecimiento
- Secuencias: Cada punto mantiene secuencias independientes por tipo de documento
- Eliminación: Solo se pueden eliminar puntos sin documentos pendientes
- Límites: Máximo 999 puntos de emisión por establecimiento
- Tipos de Documento: Cada punto puede manejar múltiples tipos de documentos
- Auditoría: Todas las operaciones quedan registradas en logs del sistema
- Respaldos: Se recomienda respaldar secuencias antes de operaciones críticas