> 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
