PHPackages                             l2ernestoo/facturalesgt - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. l2ernestoo/facturalesgt

ActiveLibrary[API Development](/categories/api)

l2ernestoo/facturalesgt
=======================

Laravel package for Guatemalan FEL certification with Ainnova / Guatefacturas.

v1.0.2(1mo ago)016MITPHPPHP ^8.2

Since Jun 6Pushed 1mo agoCompare

[ Source](https://github.com/L2Ernestoo/facturales)[ Packagist](https://packagist.org/packages/l2ernestoo/facturalesgt)[ RSS](/packages/l2ernestoo-facturalesgt/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (7)Versions (4)Used By (0)

FacturalesGT
============

[](#facturalesgt)

FacturalesGT es un package Laravel para emitir, almacenar y anular documentos FEL de Guatemala desde aplicaciones propias, puntos de venta, ERPs o sistemas administrativos.

La primera version esta disenada para trabajar con el certificador **Ainnova / Guatefacturas** mediante su servicio SOAP. El package mantiene una arquitectura extensible para agregar otros certificadores sin acoplar la logica fiscal a modelos de una aplicacion especifica.

Caracteristicas
---------------

[](#caracteristicas)

- Configuracion desde base de datos, no desde `.env`.
- Credenciales cifradas con `Laravel Crypt`.
- Empresa emisora, sucursales fiscales, credenciales, documentos, items y anulaciones.
- Builders para `FACT`, `FCAM`, `FPEQ`, `FCAP`, `FESP`, `NABN`, `RDON`, `RECI`, `NDEB` y `NCRE`.
- Certificacion y anulacion con Ainnova / Guatefacturas.
- Snapshots de documentos emitidos para auditoria.
- Mapeo independiente del modelo fuente: el package no conoce `Order`, `Sale`, `Invoice` ni ningun modelo de tu app.
- Soporte para limites mensuales de DTE y configuracion POS por sucursal.

Requisitos
----------

[](#requisitos)

- PHP `^8.2`
- Laravel `^11`, `^12` o `^13`
- Extensiones PHP `curl` y `simplexml`
- Una aplicacion Laravel con `APP_KEY` configurado para poder cifrar credenciales

Instalacion
-----------

[](#instalacion)

Cuando el package ya este publicado en Packagist:

```
composer require l2ernestoo/facturalesgt
php artisan migrate
```

Durante desarrollo local puedes usar un repository tipo `path`:

```
{
  "repositories": [
    {
      "type": "path",
      "url": "../LC-FEL",
      "options": { "symlink": true }
    }
  ],
  "require": {
    "l2ernestoo/facturalesgt": "dev-master"
  }
}
```

Luego ejecuta:

```
composer update l2ernestoo/facturalesgt
php artisan migrate
```

Configuracion opcional
----------------------

[](#configuracion-opcional)

El package carga migraciones automaticamente. Si quieres personalizar defaults tecnicos o nombres de tablas, publica el config:

```
php artisan vendor:publish --tag=fel-config
```

El archivo `config/fel.php` no debe usarse para guardar usuarios, passwords o URLs privadas por ambiente. Esas credenciales se guardan en base de datos.

Tablas creadas
--------------

[](#tablas-creadas)

- `fel_companies`: empresa emisora principal, NIT, regimen, certificador, modo y limites.
- `fel_company_credentials`: usuario FEL, password FEL, basic auth, URLs y maquina.
- `fel_branch_settings`: relacion entre empresa emisora y sucursal del sistema.
- `fel_documents`: documentos emitidos o con error.
- `fel_document_items`: snapshot de lineas certificadas.
- `fel_annulments`: anulaciones y respuesta del certificador.

Los nombres se pueden cambiar desde `config/fel.php`.

Crear configuracion Ainnova / Guatefacturas
-------------------------------------------

[](#crear-configuracion-ainnova--guatefacturas)

```
use Lc\Fel\Models\FelBranchSetting;
use Lc\Fel\Models\FelCompany;
use Lc\Fel\Models\FelCompanyCredential;

$company = FelCompany::create([
    'name' => 'Mi Empresa, S.A.',
    'nit' => '1234567',
    'regime' => 'general', // general, pequeno_contribuyente, etc.
    'certifier' => 'guatefacturas',
    'mode' => 'test', // test o prod
    'default_document_type' => 'FACT',
    'show_pos_switch' => true,
    'auto_mark_pos_switch' => true,
    'monthly_dte_limit' => 1000,
]);

FelCompanyCredential::create([
    'fel_company_id' => $company->id,
    'user' => 'USUARIO_FEL',
    'password' => 'PASSWORD_FEL',
    'basic_user' => 'BASIC_USER',
    'basic_password' => 'BASIC_PASSWORD',
    'url_test' => 'https://dte.guatefacturas.com/webservices63/feltestSB/Guatefac',
    'url_prod' => 'https://dte.guatefacturas.com/webservices63/fel/Guatefac',
    'machine_id' => '1',
]);

FelBranchSetting::create([
    'fel_company_id' => $company->id,
    'branch_source_id' => 1, // ID de la sucursal en tu app
    'fiscal_name' => 'Sucursal Principal',
    'address' => 'Ciudad',
    'establishment_code' => '1',
    'is_active' => true,
]);
```

> Nota: `password` y `basic_password` se cifran automaticamente. No los guardes en `.env`.

Mapear una venta, orden o factura
---------------------------------

[](#mapear-una-venta-orden-o-factura)

Cada aplicacion debe convertir su modelo fuente a `FelDocumentData`. Para eso puedes implementar `FelSourceMapperInterface`.

```
namespace App\Services\Fel;

use App\Models\Order;
use Lc\Fel\Contracts\FelSourceMapperInterface;
use Lc\Fel\Data\FelBranchData;
use Lc\Fel\Data\FelCompanyData;
use Lc\Fel\Data\FelDocumentData;
use Lc\Fel\Data\FelItemData;
use Lc\Fel\Data\FelReceiverData;
use Lc\Fel\Repositories\DatabaseFelConfigRepository;

class OrderFelMapper implements FelSourceMapperInterface
{
    public function __construct(
        private readonly DatabaseFelConfigRepository $config,
    ) {
    }

    public function map(mixed $source, array $options = []): FelDocumentData
    {
        /** @var Order $source */
        $company = $this->config->company($options['company_id'] ?? null);
        $branch = $this->config->branchSetting($source->branch_id, $company?->id);

        return new FelDocumentData(
            documentType: $options['document_type'] ?? $company->default_document_type,
            reference: 'ORD-' . $source->id,
            date: now(),
            company: new FelCompanyData(
                id: $company->id,
                name: $company->name,
                nit: $company->nit,
                regime: $company->regime,
                certifier: $company->certifier,
                mode: $company->mode,
                monthlyDteLimit: $company->monthly_dte_limit,
            ),
            branch: new FelBranchData(
                id: $branch->id,
                sourceBranchId: $branch->branch_source_id,
                companyId: $company->id,
                name: $branch->fiscal_name,
                address: $branch->address,
                establishmentCode: $branch->establishment_code,
                logoPath: $branch->logo_path,
            ),
            receiver: new FelReceiverData(
                nit: $options['nit'] ?? 'CF',
                name: $options['name'] ?? 'Consumidor Final',
                address: $options['address'] ?? 'Ciudad',
            ),
            items: $source->items->map(fn ($item) => new FelItemData(
                code: (string) $item->product_id,
                description: $item->product->name,
                quantity: (float) $item->quantity,
                unitPrice: (float) $item->price,
                measure: '1',
                discount: 0,
                metadata: ['source_item_id' => $item->id],
            ))->all(),
            total: (float) $source->total,
            sourceType: Order::class,
            sourceId: $source->id,
            options: $options,
        );
    }
}
```

Emitir un DTE
-------------

[](#emitir-un-dte)

```
use App\Models\Order;
use App\Services\Fel\OrderFelMapper;
use Lc\Fel\Services\FelManager;

$order = Order::with(['items.product'])->findOrFail($id);

$data = app(OrderFelMapper::class)->map($order, [
    'document_type' => 'FACT',
    'nit' => 'CF',
    'name' => 'Consumidor Final',
    'address' => 'Ciudad',
]);

$result = app(FelManager::class)->issue($data);

if ($result['success']) {
    $document = $result['document'];

    echo $document->fel_uuid;
    echo $document->fel_serie;
    echo $document->fel_preimpreso;
}
```

Si Ainnova / Guatefacturas responde correctamente, el documento queda con status `CERTIFIED`. Si el certificador falla, queda con status `ERROR` y se conserva `request_xml`, `soap_request`, `response_body` o `error_message` segun aplique.

Reintentar un documento con error
---------------------------------

[](#reintentar-un-documento-con-error)

```
use Lc\Fel\Models\FelDocument;
use Lc\Fel\Services\FelManager;

$document = FelDocument::with('items')->findOrFail($documentId);
$data = app(OrderFelMapper::class)->map($order, $document->metadata['options'] ?? []);

$result = app(FelManager::class)->certifyExisting($document, $data);
```

Anular un DTE
-------------

[](#anular-un-dte)

```
use Lc\Fel\Models\FelDocument;
use Lc\Fel\Services\FelManager;

$document = FelDocument::where('fel_uuid', $uuid)->firstOrFail();

$result = app(FelManager::class)->annul($document, 'Anulacion solicitada por el cliente', [
    'user_id' => auth()->id(),
]);
```

Si la anulacion es aceptada, el documento pasa a status `ANNULLED` y se crea un registro en `fel_annulments`.

Configuracion para POS
----------------------

[](#configuracion-para-pos)

Puedes leer la configuracion activa por sucursal:

```
use Lc\Fel\Services\FelManager;

$settings = app(FelManager::class)->posSettings($branchId);
```

El resultado incluye empresa activa, documento por defecto, si debe mostrarse un switch de FEL, si debe marcarse automaticamente y el uso mensual:

```
[
    'enabled' => true,
    'company_id' => 1,
    'default_document_type' => 'FACT',
    'show_pos_switch' => true,
    'auto_mark_pos_switch' => true,
    'usage' => [
        'limit' => 1000,
        'used' => 150,
        'remaining' => 850,
        'percent' => 15.0,
    ],
]
```

Tipos de documento soportados
-----------------------------

[](#tipos-de-documento-soportados)

TipoDescripcion`FACT`Factura`FCAM`Factura cambiaria`FPEQ`Factura pequeno contribuyente`FCAP`Factura cambiaria pequeno contribuyente`FESP`Factura especial`NABN`Nota de abono`RDON`Recibo por donacion`RECI`Recibo`NDEB`Nota de debito`NCRE`Nota de creditoPara `NCRE` y `NDEB`, envia el documento asociado en `options`:

```
[
    'associated_document' => [
        'serie' => 'A1',
        'preimpreso' => '123',
    ],
]
```

Respuesta certificada
---------------------

[](#respuesta-certificada)

El package guarda datos importantes devueltos por Ainnova / Guatefacturas:

```
$document->fel_uuid;       // NumeroAutorizacion
$document->fel_serie;      // Serie
$document->fel_preimpreso; // Preimpreso

$document->metadata['certifier_response'] ?? [];
```

`metadata.certifier_response` puede incluir `nombre`, `direccion`, `telefono` y `referencia`. Esto es util para tickets, PDFs, reportes y auditoria.

Extender a otro certificador
----------------------------

[](#extender-a-otro-certificador)

Implementa `CertifierInterface` y registralo en `config/fel.php`:

```
'certifiers' => [
    'guatefacturas' => Lc\Fel\Services\Certifiers\GuatefacturasCertifier::class,
    'otro' => App\Fel\Certifiers\OtroCertifier::class,
],
```

Luego configura la empresa con `certifier = otro`.

Ejecutar pruebas
----------------

[](#ejecutar-pruebas)

```
composer install
vendor/bin/phpunit
```

Licencia
--------

[](#licencia)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

48d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e27f5204ba8b53c1c341cd0671d961ccd74ba4394ee761a47dfd611c3b335875?d=identicon)[thorcito](/maintainers/thorcito)

---

Top Contributors

[![L2Ernestoo](https://avatars.githubusercontent.com/u/42287457?v=4)](https://github.com/L2Ernestoo "L2Ernestoo (3 commits)")

---

Tags

laravelfactura-electronicaGuatemalafelainnovaguatefacturas

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/l2ernestoo-facturalesgt/health.svg)

```
[![Health](https://phpackages.com/badges/l2ernestoo-facturalesgt/health.svg)](https://phpackages.com/packages/l2ernestoo-facturalesgt)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k95.4M321](/packages/laravel-horizon)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k30.2M151](/packages/laravel-cashier)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
