> For the complete documentation index, see [llms.txt](https://raanh-1.gitbook.io/hazem-package/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://raanh-1.gitbook.io/hazem-package/invoices.md).

# Invoices

## ZATCA Invoice System Documentation

### Table of Contents

1. Invoice Setup
2. Creating Invoices
3. Submitting Invoices
4. Returns and Credit Notes
5. Status Checking
6. Available Methods
7. Important Notes

### Invoice Setup

#### Adding ZATCA Invoice Capability

First, add the HasZatcaInvoice trait to your model:

```php
use Hazem\Zatca\Traits\HasZatcaInvoice;

class Order extends Model
{
    use HasZatcaInvoice;
    
    protected function prepareZatcaInvoiceData()
    {
        $items = $this->prepareZatcaItems();
        return [
            'invoice_number' => $this->invoice_no,
            'total_amount' => round($this->final_total, 2),
            'vat_amount' => collect($items)->sum(function ($item) {
                return round($item['vat'] * $item['quantity'], 2);
            }),
            'is_pos' => true,
            'is_invoice' => $this->type === 'sell',
            'items' => $items,
            'date' => $this->transaction_date,
            // Buyer information
            'buyer_name' => $this->contact->name ?? null,
            'buyer_tax_number' => null,
            'buyer_address' => null,
            'buyer_city' => null,
            'buyer_state' => null,
            'buyer_postal' => null,
            'buyer_building_no' => null
        ];
    }

    protected function prepareZatcaItems()
    {
        return $this->sell_lines->map(function($item) {
            return [
                'name' => $item->product?->name,
                'quantity' => $item->quantity,
                'price' => round($item->unit_price, 2),
                'vat' => round(round($item->unit_price, 2) * 0.15, 2)
            ];
        })->toArray();
    }
}
```

> **Important Note**: Always round monetary values to 2 decimal places to ensure accuracy in calculations.

### Creating Invoices

#### Using the Fluent Interface

The fluent interface provides a clean and chainable way to create invoices:

```php
$invoice = Zatca::prepare()
    ->setInvoiceNumber('INV-001')              // Unique invoice number
    ->setTotalAmount(115.00)                   // Total including VAT
    ->setVatAmount(15.00)                      // VAT amount
    ->setBuyerName('John Doe')                 // Customer name
    ->setBuyerTaxNumber('1234567890')          // Customer VAT number
    ->setBuyerAddress('123 Main St')           // Customer address
    ->setBuyerCity('Riyadh')                   // Customer city
    ->setBuyerState('Riyadh')                  // Customer state/region
    ->setBuyerPostal('12345')                  // Customer postal code
    ->setBuyerBuildingNumber('1234')           // Customer building number
    ->isPOS()                                  // Mark as POS transaction
    ->isInvoice(true)                          // true for sales, false for returns
    ->setDate(now())                           // Transaction date
    ->addItem('Product 1', 1, 100.00, 15.00);  // Add items
```

> **Pro Tip**: You can chain multiple `addItem()` calls to add multiple products to the invoice.

### Submitting Invoices

There are two methods to submit invoices to ZATCA:

#### 1. Basic Submission

```php
$result = $order->submitToZatca($invoice->toArray());
```

#### 2. Custom Data Submission

```php
$result = $order->submitToZatca([
    'invoice_number' => 'INV-001',
    'total_amount' => 115.00,
    'vat_amount' => 15.00,
    'items' => [
        [
            'name' => 'Product 1',
            'quantity' => 1,
            'price' => 100.00,
            'vat' => 15.00
        ]
    ]
]);
```

> **Best Practice**: Always validate your data before submission to avoid rejection.

### Returns and Credit Notes

To create a return/credit note invoice:

```php
$returnInvoice = Zatca::prepare()
    ->setInvoiceNumber('RET-001')          // Unique return number
    ->setTotalAmount(-115.00)              // Negative amount for returns
    ->setVatAmount(-15.00)                 // Negative VAT for returns
    ->setBuyerName('John Doe')
    ->isPOS()
    ->isInvoice(false)                     // Mark as return/credit note
    ->setDate(now())
    ->addItem('Product 1', 1, -100.00, -15.00);  // Negative values

$result = $order->submitToZatca($returnInvoice->toArray());
```

> **Critical Notes for Returns**:
>
> * All monetary values must be negative
> * Reference the original invoice number when possible
> * Use a unique return/credit note number
> * Keep the same VAT rate as the original invoice

### Status Checking

Monitor your invoice status:

```php
// Check submission status
if ($order->isSubmittedToZatca()) {
    // Get current status
    $status = $order->getZatcaStatus();
    
    // Check for errors
    if ($order->hasZatcaErrors()) {
        $errors = $order->getZatcaErrors();
    }
}
```

### Available Methods

#### Invoice Operations

```php
// Zatca Facade Methods
Zatca::prepare();                                    // Start new invoice
Zatca::submitInvoice($businessId, $invoiceData);    // Submit regular invoice
Zatca::submitSimplifiedInvoice($businessId, $data); // Submit simplified invoice
Zatca::submitStandardInvoice($businessId, $data);   // Submit standard invoice
Zatca::getInvoiceStatus($businessId, $invoiceNo);   // Check status
Zatca::validateInvoice($invoiceData);               // Validate before submit
Zatca::generateQRCode($invoiceData);                // Generate QR code

// Model Methods (HasZatcaInvoice Trait)
$model->order();                   // Get order relationship
$model->submitToZatca();          // Submit invoice
$model->isSubmittedToZatca();     // Check submission status
$model->getZatcaStatus();         // Get invoice status
$model->hasZatcaErrors();         // Check for errors
$model->getZatcaErrors();         // Get error details
```

### Important Notes

#### General Guidelines

1. **Data Accuracy**
   * Always validate data before submission
   * Use proper rounding for monetary values
   * Ensure all required fields are filled
2. **Error Handling**
   * Always check for errors after submission
   * Log all errors for debugging
   * Implement proper error handling in your code
3. **Performance**
   * Consider implementing queueing for bulk submissions
   * Cache device information when possible
   * Monitor API rate limits

#### Common Pitfalls to Avoid

1. Not handling decimal places properly
2. Forgetting to mark returns as non-invoices
3. Missing required buyer information
4. Incorrect VAT calculations
5. Not validating data before submission

#### Best Practices

1. **Data Validation**

   ```php
   // Validate before submission
   $isValid = Zatca::validateInvoice($invoiceData);
   if ($isValid) {
       $result = $order->submitToZatca($invoiceData);
   }
   ```
2. **Error Handling**

   ```php
   try {
       $result = $order->submitToZatca($invoiceData);
   } catch (ZatcaException $e) {
       Log::error('ZATCA submission failed: ' . $e->getMessage());
       // Handle error appropriately
   }
   ```
3. **Status Monitoring**

   ```php
   // Implement status checking with retry logic
   $maxRetries = 3;
   $attempt = 0;
   do {
       $status = $order->getZatcaStatus();
       if ($status === 'REPORTED') break;
       sleep(2); // Wait before retry
   } while (++$attempt < $maxRetries);
   ```

#### Security Considerations

1. Store sensitive data securely
2. Implement proper authentication
3. Use HTTPS for all API communications
4. Regular audit of access logs
5. Proper handling of cryptographic materials


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://raanh-1.gitbook.io/hazem-package/invoices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
