Skip to main content
POST
/
api
/
ventas
Crear Venta
curl --request POST \
  --url https://api.example.com/api/ventas \
  --header 'Content-Type: application/json' \
  --data '
{
  "id_tido": 123,
  "fecha_emision": "<string>",
  "serie": "<string>",
  "numero": 123,
  "subtotal": 123,
  "igv": 123,
  "total": 123,
  "tipo_moneda": "<string>",
  "id_cliente": 123,
  "cliente_documento": "<string>",
  "cliente_datos": "<string>",
  "cliente_direccion": "<string>",
  "id_tipo_pago": 123,
  "pago_id_tipo_pago": 123,
  "pago_numero_operacion": "<string>",
  "pago_banco": "<string>",
  "productos": [
    {
      "productos.*.id_producto": 123,
      "productos.*.descripcion_libre": "<string>",
      "productos.*.cantidad": 123,
      "productos.*.precio_unitario": 123,
      "productos.*.subtotal": 123,
      "productos.*.igv": 123,
      "productos.*.total": 123,
      "productos.*.descripcion": "<string>",
      "productos.*.codigo_producto": "<string>",
      "productos.*.unidad_medida": "<string>",
      "productos.*.tipo_afectacion_igv": "<string>"
    }
  ],
  "afecta_stock": true,
  "cotizacion_id": 123,
  "nota_venta_id": 123,
  "empresas_ids": [
    {}
  ]
}
'
{
  "success": true,
  "message": "<string>",
  "venta": {
    "id_venta": 123,
    "numero_completo": "<string>"
  }
}

Endpoint

POST /api/ventas

Autenticación

Requiere token de autenticación Bearer:
Authorization: Bearer {token}

Permisos Requeridos

  • ventas.create

Descripción

Crea una nueva venta con las siguientes funcionalidades:
  • Validación automática de tipo de documento según cliente (RUC=Factura, DNI/CE=Boleta)
  • Generación automática de número correlativo por serie
  • Creación automática de clientes si no existen
  • Descuento automático de stock de productos (configurable)
  • Registro de movimientos de stock
  • Soporte para productos libres (sin código)
  • Vinculación con cotizaciones y notas de venta
  • Gestión de cuotas para ventas a crédito
  • Carga de voucher de pago

Parámetros de Solicitud

Campos Principales

id_tido
integer
required
ID del tipo de documento:
  • 1 = Boleta de Venta
  • 2 = Factura
  • 6 = Nota de Venta
Debe existir en documentos_sunat tabla.
fecha_emision
string
required
Fecha de emisión en formato YYYY-MM-DD
serie
string
required
Serie del comprobante (máx 4 caracteres). Ejemplos: F001, B001, NV01
numero
integer
required
Número correlativo (se genera automáticamente si no se envía). El sistema usa el máximo entre:
  • Última venta de la serie + 1
  • Número base configurado en documentos_empresas + 1
subtotal
number
required
Subtotal antes de IGV (mínimo 0)
igv
number
required
Monto del IGV calculado (mínimo 0)
total
number
required
Total de la venta incluyendo IGV (mínimo 0)
tipo_moneda
string
required
Código de moneda: PEN (Soles) o USD (Dólares)

Campos de Cliente

id_cliente
integer
ID del cliente existente. Si no se envía, se buscará o creará según documento.
cliente_documento
string
Número de documento del cliente (máx 15 caracteres).Validación importante:
  • Factura (id_tido=2) requiere RUC (11 dígitos)
  • Boleta (id_tido=1) no permite RUC, usa DNI (8) o CE
cliente_datos
string
Nombre o razón social (máx 250 caracteres)
cliente_direccion
string
Dirección del cliente (máx 500 caracteres)

Campos de Pago

id_tipo_pago
integer
Tipo de pago: 1 = Contado, 2 = Crédito
pago_id_tipo_pago
integer
ID del método de pago (efectivo, tarjeta, transferencia, etc.)
pago_numero_operacion
string
Número de operación o referencia del pago (máx 50 caracteres)
pago_banco
string
Nombre del banco (máx 100 caracteres)
pago_voucher
file
Imagen del voucher de pago. Formatos: jpeg, png, jpg, webp. Máximo 2MB.

Productos (Array Requerido)

productos
array
required
Array de productos de la venta (mínimo 1 producto requerido)

Campos Opcionales Avanzados

afecta_stock
boolean
Indica si la venta debe descontar stock. Por defecto: true (excepto para Notas de Venta que son false)
cotizacion_id
integer
ID de la cotización de origen. Si se envía, la cotización se marca como “aprobada”.
nota_venta_id
integer
ID de la nota de venta de origen. Si se envía, la nota se marca como “vendida” (estado 3).
empresas_ids
array
Array de IDs de empresas para ventas multi-empresa (tabla pivot venta_empresa)

Lógica de Negocio

Validación de Documentos

  1. Factura (id_tido=2): Solo permite RUC de 11 dígitos. Rechaza DNI.
  2. Boleta (id_tido=1): Permite DNI (8) o CE. Rechaza RUC de 11 dígitos.
  3. Nota de Venta (id_tido=6): Sin restricciones.

Creación Automática de Clientes

Si no se envía id_cliente:
  • Sistema busca cliente por documento en la empresa
  • Si no existe, lo crea automáticamente con:
    • tipo_doc: 6 (RUC 11 dig), 1 (DNI 8 dig), 4 (CE otros)
    • Si no hay documento ni nombre: usa “CLIENTES VARIOS” con documento 00000000

Numeración Automática

El sistema calcula el próximo número usando:
$ultimaVenta = max(ventas.numero WHERE serie = {serie});
$numeroBase = documentos_empresas.numero WHERE serie = {serie};
$proximoNumero = max($ultimaVenta, $numeroBase) + 1;
Luego actualiza documentos_empresas.numero con el nuevo valor.

Gestión de Stock

Descuento automático si afecta_stock = true (y no es producto libre):
  1. Decrementa productos.cantidad
  2. Actualiza productos.ultima_salida = now()
  3. Crea registro en movimientos_stock:
    • tipo_movimiento = “salida”
    • tipo_documento = “venta”
    • Registra stock_anterior y stock_nuevo
Productos libres (con descripcion_libre):
  • No descuentan stock
  • Se crean en catálogo con código LIB-0001, LIB-0002, etc.
  • Almacén por defecto: 1

Respuesta Exitosa (201)

success
boolean
true si la venta se creó exitosamente
message
string
“Venta creada exitosamente”
venta
object
Datos de la venta creada

Ejemplo de Respuesta Exitosa

{
  "success": true,
  "message": "Venta creada exitosamente",
  "venta": {
    "id_venta": 126,
    "numero_completo": "F001-000349"
  }
}

Errores

Error de Validación (422)

{
  "success": false,
  "message": "Error de validación",
  "errors": {
    "productos": ["Debe agregar al menos un producto a la venta."],
    "productos.0.cantidad": ["La cantidad debe ser mayor a 0."]
  }
}

Error de Documento Inválido (422)

Factura con DNI:
{
  "success": false,
  "message": "Para FACTURA se requiere RUC (11 dígitos). No se puede emitir factura con DNI."
}
Boleta con RUC:
{
  "success": false,
  "message": "Para BOLETA use DNI u CE. Para RUC emita una Factura."
}

Error del Servidor (500)

{
  "success": false,
  "message": "Error al crear la venta"
}

Ejemplo de Solicitud Completa

curl -X POST "https://facturacion.santodomingo.pe/api/ventas" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
  -H "Content-Type: application/json" \
  -d '{
    "id_tido": 2,
    "fecha_emision": "2024-03-15",
    "serie": "F001",
    "numero": 350,
    "subtotal": 847.46,
    "igv": 152.54,
    "total": 1000.00,
    "tipo_moneda": "PEN",
    "id_tipo_pago": 1,
    "cliente_documento": "20612706702",
    "cliente_datos": "SANTO DOMINGO SAC",
    "cliente_direccion": "Av. Los Pinos 123",
    "afecta_stock": true,
    "productos": [
      {
        "id_producto": 45,
        "cantidad": 10,
        "precio_unitario": 100.00,
        "subtotal": 847.46,
        "igv": 152.54,
        "total": 1000.00,
        "unidad_medida": "NIU",
        "tipo_afectacion_igv": "10"
      }
    ],
    "pago_id_tipo_pago": 1,
    "pago_numero_operacion": "OP-2024-0315-001",
    "pago_banco": "BCP"
  }'

Ejemplo con Producto Libre

{
  "id_tido": 1,
  "fecha_emision": "2024-03-15",
  "serie": "B001",
  "numero": 893,
  "subtotal": 84.75,
  "igv": 15.25,
  "total": 100.00,
  "tipo_moneda": "PEN",
  "id_tipo_pago": 1,
  "cliente_documento": "12345678",
  "cliente_datos": "JUAN PEREZ LOPEZ",
  "afecta_stock": false,
  "productos": [
    {
      "descripcion_libre": "Servicio de consultoría técnica",
      "cantidad": 1,
      "precio_unitario": 100.00,
      "subtotal": 84.75,
      "igv": 15.25,
      "total": 100.00,
      "unidad_medida": "ZZ",
      "tipo_afectacion_igv": "10"
    }
  ]
}

Transaccionalidad

Toda la operación se ejecuta dentro de una transacción de base de datos (DB::transaction). Si cualquier paso falla, todos los cambios se revierten:
  • Creación de venta
  • Creación de productos_ventas
  • Descuento de stock
  • Registro de movimientos
  • Creación de pagos
  • Actualización de cotizaciones/notas

Código de Referencia

Ver implementación en app/Http/Controllers/VentasController.php:80 método store()

Build docs developers (and LLMs) love