Skip to main content
The Sales and Purchase Books (Libro de Ventas y Compras) are monthly reports required by Chile’s SII that summarize all electronic documents issued and received during a period.

Overview

The BookComponent handles the generation and management of:
  • Sales Book (Libro de Ventas): Summary of all documents issued (invoices, receipts, credit/debit notes)
  • Purchase Book (Libro de Compras): Summary of all documents received from suppliers
These books must be submitted to SII monthly and include tax calculations, document totals, and statistical information.

Accessing the Book Component

$bookComponent = $app->getPackage('billing')
    ->getComponent('book');
The BookComponent is currently under development. Full functionality will be available in future releases. This guide covers the planned architecture and usage patterns.

Sales Book (Libro de Ventas)

The sales book summarizes all documents you’ve issued to customers:

Documents Included

Invoices

  • Factura Afecta (33)
  • Factura Exenta (34)
  • Factura de Exportación (110)

Receipts

  • Boleta Afecta (39)
  • Boleta Exenta (41)

Credit Notes

  • Nota de Crédito (61)
  • Nota de Crédito Exportación (112)

Debit Notes

  • Nota de Débito (56)
  • Nota de Débito Exportación (111)

Expected Usage Pattern

// Planned API for generating sales book
$salesBookWorker = $bookComponent->getSalesBookWorker();

// Generate sales book for a period
$salesBook = $salesBookWorker->generate(
    company: '12345678-5',
    period: '2025-01',  // Year-Month format
    documents: $issuedDocuments,  // Array of DocumentBag or Document entities
    options: [
        'include_receipts' => true,
        'include_export' => true,
    ]
);

// Export to XML for SII submission
$xmlContent = $salesBook->toXml();
file_put_contents('libro_ventas_202501.xml', $xmlContent);

// Get summary data
$summary = $salesBook->getSummary();
echo "Total Sales: " . $summary['total_sales'];
echo "Total IVA: " . $summary['total_iva'];

Purchase Book (Libro de Compras)

The purchase book summarizes all documents received from suppliers:

Expected Usage Pattern

// Planned API for generating purchase book
$purchaseBookWorker = $bookComponent->getPurchaseBookWorker();

// Generate purchase book for a period
$purchaseBook = $purchaseBookWorker->generate(
    company: '12345678-5',
    period: '2025-01',
    documents: $receivedDocuments,  // Supplier invoices
    options: [
        'include_imports' => true,
    ]
);

// Export to XML
$xmlContent = $purchaseBook->toXml();
file_put_contents('libro_compras_202501.xml', $xmlContent);

// Get summary
$summary = $purchaseBook->getSummary();
echo "Total Purchases: " . $summary['total_purchases'];
echo "Recoverable IVA: " . $summary['recoverable_iva'];

Book Structure

Both sales and purchase books follow a similar structure:
1

Identification (Caratula)

Book header with company information, period, and summary totals.
[
    'RutEmisorLibro' => '12345678-5',
    'RazonSocial' => 'Mi Empresa S.A.',
    'PeriodoTributario' => '2025-01',
    'FchResol' => '2014-01-01',
    'NroResol' => 80,
    'TipoLibro' => 'MENSUAL',
    'TipoEnvio' => 'TOTAL',
    // Summary totals
    'TotalesLibro' => [
        'TotMntNeto' => 10000000,
        'TotMntIVA' => 1900000,
        'TotMntTotal' => 11900000,
    ],
]
2

Document Details (Detalle)

Individual line items for each document in the period.
[
    [
        'TpoDoc' => 33,
        'NroDoc' => 150,
        'TasaImp' => 19,
        'FchDoc' => '2025-01-15',
        'RUTDoc' => '87654321-9',
        'RznSoc' => 'Cliente S.A.',
        'MntNeto' => 420168,
        'MntIVA' => 79832,
        'MntTotal' => 500000,
    ],
    // More documents...
]
3

Summary Sections

Statistical summaries grouped by document type and tax rate.

Collecting Documents for Books

Organize documents by period for book generation:
// Example: Collect sales for January 2025
class DocumentCollector
{
    private $documents = [];
    
    public function addDocument(DocumentInterface $document)
    {
        $this->documents[] = $document;
    }
    
    public function getDocumentsByPeriod(string $period): array
    {
        // Filter documents by period (YYYY-MM)
        return array_filter($this->documents, function($doc) use ($period) {
            $docDate = $doc->getFechaEmision();
            return substr($docDate, 0, 7) === $period;
        });
    }
    
    public function getSalesSummary(string $period): array
    {
        $docs = $this->getDocumentsByPeriod($period);
        
        $summary = [
            'total_documents' => count($docs),
            'total_net' => 0,
            'total_iva' => 0,
            'total_amount' => 0,
        ];
        
        foreach ($docs as $doc) {
            $summary['total_net'] += $doc->getMontoNeto();
            $summary['total_iva'] += $doc->getIVA();
            $summary['total_amount'] += $doc->getMontoTotal();
        }
        
        return $summary;
    }
}

// Usage
$collector = new DocumentCollector();

// Add documents as you create them throughout the month
$bag = $documentComponent->bill($data, $caf, $certificate);
$collector->addDocument($bag->getDocument());

// At month end, generate summary
$summary = $collector->getSalesSummary('2025-01');
print_r($summary);

Monthly Workflow

1

Throughout the Month

Create and store all documents:
// For each sale/purchase
$bag = $documentComponent->bill($data, $caf, $certificate);
$document = $bag->getDocument();

// Store document
$db->saveDocument([
    'folio' => $document->getFolio(),
    'type' => $document->getCodigo(),
    'date' => $document->getFechaEmision(),
    'total' => $document->getMontoTotal(),
    'xml' => $document->getXml(),
    'period' => date('Y-m', strtotime($document->getFechaEmision())),
]);
2

End of Month

Retrieve all documents for the period:
$period = '2025-01';
$documents = $db->getDocumentsByPeriod($period);
3

Generate Books

Create sales and purchase books:
// Sales book from issued documents
$salesDocs = array_filter($documents, fn($d) => $d['direction'] === 'issued');
$salesBook = $salesBookWorker->generate('12345678-5', $period, $salesDocs);

// Purchase book from received documents
$purchaseDocs = array_filter($documents, fn($d) => $d['direction'] === 'received');
$purchaseBook = $purchaseBookWorker->generate('12345678-5', $period, $purchaseDocs);
4

Submit to SII

Send books to SII:
// Send sales book
$salesXml = $salesBook->toXml();
$trackId1 = $siiWorker->sendXmlDocument($request, $salesXml, $company);

// Send purchase book
$purchaseXml = $purchaseBook->toXml();
$trackId2 = $siiWorker->sendXmlDocument($request, $purchaseXml, $company);

// Check status
$status1 = $siiWorker->checkXmlDocumentSentStatus($request, $trackId1, $company);
$status2 = $siiWorker->checkXmlDocumentSentStatus($request, $trackId2, $company);

Book Validation

Validate books before submission:
// Expected validation API
$validator = $bookComponent->getBookValidatorWorker();

try {
    // Validate sales book
    $validator->validate($salesBook);
    echo "Sales book is valid\n";
    
    // Validate against expected totals
    $expectedTotal = $db->getSumOfSales($period);
    $bookTotal = $salesBook->getTotalMonto();
    
    if (abs($expectedTotal - $bookTotal) > 0.01) {
        throw new Exception("Book total mismatch: expected {$expectedTotal}, got {$bookTotal}");
    }
    
} catch (Exception $e) {
    echo "Validation error: " . $e->getMessage();
}

Handling Corrections

If you need to correct a submitted book:
// Generate replacement book
$salesBook = $salesBookWorker->generate(
    company: '12345678-5',
    period: '2025-01',
    documents: $correctedDocuments,
    options: [
        'tipo_envio' => 'RECTIFICA',  // Correction type
        'folio_notificacion' => 123,  // Previous submission folio
    ]
);

// Submit correction
$xmlContent = $salesBook->toXml();
$trackId = $siiWorker->sendXmlDocument($request, $xmlContent, $company);

Database Schema Example

Store documents for book generation:
CREATE TABLE documents (
    id INT PRIMARY KEY AUTO_INCREMENT,
    company_rut VARCHAR(12) NOT NULL,
    direction ENUM('issued', 'received') NOT NULL,
    document_type INT NOT NULL,
    folio INT NOT NULL,
    issue_date DATE NOT NULL,
    period VARCHAR(7) NOT NULL,  -- YYYY-MM format
    recipient_rut VARCHAR(12),
    net_amount DECIMAL(15,2),
    iva_amount DECIMAL(15,2),
    total_amount DECIMAL(15,2),
    xml_content TEXT,
    ted_stamp TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_period (company_rut, period, direction),
    INDEX idx_date (issue_date),
    UNIQUE KEY unique_doc (company_rut, document_type, folio)
);

CREATE TABLE book_submissions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    company_rut VARCHAR(12) NOT NULL,
    book_type ENUM('sales', 'purchases') NOT NULL,
    period VARCHAR(7) NOT NULL,
    track_id INT,
    status VARCHAR(50),
    xml_content TEXT,
    submitted_at TIMESTAMP,
    
    UNIQUE KEY unique_submission (company_rut, book_type, period)
);

Current Implementation Status

The BookComponent is currently a placeholder:
// BookComponent.php:37-53
class BookComponent extends AbstractComponent implements BookComponentInterface
{
    public function __construct()
    {
        // TODO: Agregar workers para inyección de dependencias.
    }

    public function getWorkers(): array
    {
        return [
            // TODO: Agregar workers.
        ];
    }
}
Full book generation functionality is under development. For now, you’ll need to implement custom book generation logic or use the LibreDTE web platform for book submission.

Temporary Solutions

While the BookComponent is being developed, consider:
  1. Manual aggregation: Collect document totals in your database and generate books using the SII’s provided tools
  2. Third-party services: Use LibreDTE’s web platform (https://libredte.cl) for book generation
  3. Custom implementation: Build book generation using the document data you’ve stored

Next Steps

Creating Documents

Learn how to create the documents that will be included in books

SII Integration

Understand how to submit books to SII when ready

Build docs developers (and LLMs) love