# Invoice Flow - Complete Explanation

## Your Question

> "I accept quotation to then become sales_order... then does invoice then also come from odoo or what.... how do i get it onto the portal so the customer can see it and its also saved on db."

## Answer: YES - Invoice ALWAYS Comes from Odoo

The invoice is **NEVER** created by the portal. Here's exactly how it works:

## Complete Invoice Flow

### Step 1: Customer Accepts Quotation (Portal)

```
Customer clicks "Accept Quotation"
↓
Portal → QuotationController.accept()
↓
Portal creates local SalesOrder record
Portal sends to Odoo: convertQuotationToSaleOrder()
↓
Odoo confirms quotation → Sales Order (state: 'sale')
```

**Code:**
```php
// QuotationController.php - accept() method
$salesOrder = SalesOrder::create([...]);  // Local record
$odooOrderId = $odooService->convertQuotationToSaleOrder($quotation->odoo_quotation_id);
// NOTE: Invoice generation is handled by sales team in Odoo
// Portal will sync invoices via webhook or scheduled sync job
```

### Step 2: Sales Team Generates Invoice (Odoo)

**In Odoo:**
1. Sales team opens the confirmed sales order
2. Clicks "Create Invoice" button (or automatic based on Odoo config)
3. Invoice is created in Odoo (account.move model)
4. Invoice state: 'posted' (ready for payment)

**This happens in Odoo, NOT in the portal!**

### Step 3: Invoice Synced to Portal (Two Ways)

#### Option A: Webhook (Instant) - If Configured

```
Odoo generates invoice
↓
Odoo sends webhook: POST /api/odoo/webhook
Event: 'invoice.created'
Data: { invoice: {...} }
↓
Portal → OdooController.handleWebhook()
↓
Portal → syncInvoice($invoiceData)
↓
Portal creates Invoice record in database
Portal sends email to customer
```

**Code:**
```php
// OdooController.php - handleWebhook()
case 'invoice.created':
    $this->syncInvoice($data['invoice']);
    break;

// syncInvoice() method
$invoice = Invoice::updateOrCreate(
    ['odoo_invoice_id' => $invoiceData['id']],
    [
        'customer_id' => $customer->id,
        'sales_order_id' => $salesOrder->id,
        'invoice_number' => $invoiceData['name'],
        'total_amount' => $invoiceData['amount_total'],
        'status' => 'pending',
        // ... other fields
    ]
);

// Send email notification
Mail::to($customer->email)->send(new InvoiceCreated($invoice));
```

#### Option B: Scheduled Sync (Every 5 Minutes) - Fallback

```
Scheduler runs every 5 minutes
↓
docker-compose exec scheduler php artisan sync:data invoices
↓
Portal → DataSynchronizationService.syncInvoiceData()
↓
Portal fetches invoices from Odoo
Portal creates/updates Invoice records in database
Portal sends email to customer (if new invoice)
```

**Code:**
```php
// routes/console.php
Schedule::command('sync:data invoices')->everyFiveMinutes();

// DataSynchronizationService.php
public function syncInvoiceData() {
    // Fetch invoices from Odoo
    $odooInvoices = $this->odooService->getCustomerInvoices($partnerId);
    
    // Create/update in portal database
    foreach ($odooInvoices as $invoiceData) {
        Invoice::updateOrCreate([...]);
    }
}
```

### Step 4: Customer Sees Invoice (Portal)

```
Customer logs into portal
↓
Navigates to Invoices page
↓
Portal queries local database:
Invoice::where('customer_id', $customer->id)->get()
↓
Customer sees invoice with:
- Invoice number
- Amount
- Due date
- Status
- "Pay Now" button
```

### Step 5: Customer Pays Invoice (Portal)

```
Customer clicks "Pay Now"
↓
Portal → PaymentController.processInvoicePayment()
↓
Payment Gateway (Pesepay/Bank Transfer)
↓
Payment confirmed
↓
Portal records payment
Portal sends payment to Odoo
```

## Database Flow

### Tables Involved

```
quotations
    ↓ (customer accepts)
sales_orders (created by portal, synced to Odoo)
    ↓ (sales team generates invoice in Odoo)
invoices (synced FROM Odoo to portal)
    ↓ (customer pays)
payments (created by portal, synced to Odoo)
```

### Invoice Table Structure

```sql
CREATE TABLE invoices (
    id BIGINT PRIMARY KEY,
    customer_id BIGINT,
    sales_order_id BIGINT,
    odoo_invoice_id INT,  -- Links to Odoo
    invoice_number VARCHAR,
    invoice_type VARCHAR,
    amount DECIMAL,
    tax_amount DECIMAL,
    total_amount DECIMAL,
    status VARCHAR,  -- pending, paid, cancelled
    invoice_date DATE,
    due_date DATE,
    paid_date DATE,
    description TEXT,
    line_items JSON,
    odoo_synced BOOLEAN,
    odoo_synced_at TIMESTAMP,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);
```

## Key Points

### ✅ Invoice ALWAYS Comes from Odoo

```
Portal NEVER creates invoices
Portal ONLY syncs invoices from Odoo
Portal saves invoices to local database
Customer sees invoices from local database
```

### ✅ Two Sync Methods

**1. Webhook (Instant):**
- Odoo sends webhook when invoice created
- Portal receives and syncs immediately
- Requires webhook configuration in Odoo

**2. Scheduled Sync (Every 5 minutes):**
- Scheduler runs: `php artisan sync:data invoices`
- Portal fetches all invoices from Odoo
- Portal updates local database
- Fallback if webhooks fail

### ✅ Customer Notification

When invoice is synced:
```php
Mail::to($customer->email)->send(new InvoiceCreated($invoice));
```

Email contains:
- Invoice number
- Amount due
- Due date
- Link to view invoice in portal
- "Pay Now" button

### ✅ Customer Can See Invoice

After sync, invoice is in database:
```php
// Customer views invoices
$invoices = Invoice::where('customer_id', $customer->id)
    ->orderBy('created_at', 'desc')
    ->get();
```

Portal displays:
- List of all invoices
- Invoice details
- Payment status
- "Pay Now" button (if unpaid)

## Timeline Example

```
Day 1, 10:00 AM - Customer accepts quotation
                  Portal creates sales order
                  Portal confirms in Odoo

Day 1, 10:05 AM - Scheduler syncs sales order from Odoo
                  (confirms it's in Odoo)

Day 1, 2:00 PM  - Sales team generates invoice in Odoo

Day 1, 2:00 PM  - Webhook fires (if configured)
                  Portal syncs invoice immediately
                  Customer receives email
                  
                  OR
                  
Day 1, 2:05 PM  - Scheduler runs (if no webhook)
                  Portal syncs invoice
                  Customer receives email

Day 1, 2:10 PM  - Customer logs in
                  Sees invoice in portal
                  Clicks "Pay Now"
                  Makes payment
```

## Verification

### Check if Invoice Synced

```bash
# View scheduler logs
docker-compose logs -f scheduler

# Manually trigger sync
docker-compose exec scheduler php artisan sync:data invoices

# Check database
docker-compose exec backend php artisan tinker
>>> Invoice::latest()->first()
>>> Invoice::where('customer_id', 1)->get()
```

### Check Webhook

```bash
# View webhook logs
docker-compose logs backend | grep webhook

# Check Laravel logs
docker-compose exec backend tail -f storage/logs/laravel.log
```

## Troubleshooting

### Invoice Not Appearing in Portal

**1. Check if invoice exists in Odoo:**
- Log into Odoo
- Check if invoice was created
- Verify invoice state is 'posted'

**2. Check if webhook fired:**
```bash
docker-compose logs backend | grep "invoice.created"
```

**3. Manually trigger sync:**
```bash
docker-compose exec scheduler php artisan sync:data invoices
```

**4. Check database:**
```bash
docker-compose exec backend php artisan tinker
>>> Invoice::where('odoo_invoice_id', 123)->first()
```

**5. Check logs:**
```bash
docker-compose logs scheduler
docker-compose exec backend tail -f storage/logs/laravel.log
```

### Invoice Synced but Customer Not Notified

**Check email logs:**
```bash
docker-compose logs backend | grep "Invoice notification"
```

**Test email:**
```bash
docker-compose exec backend php artisan email:test customer@email.com
```

## Summary

### How Invoice Gets to Portal

1. **Sales team generates invoice in Odoo** (manual or automatic)
2. **Odoo sends webhook** (if configured) OR **Scheduler syncs** (every 5 min)
3. **Portal receives invoice data** from Odoo
4. **Portal creates Invoice record** in local database
5. **Portal sends email** to customer
6. **Customer logs in** and sees invoice
7. **Customer can pay** invoice

### Key Takeaways

✅ Invoice **ALWAYS** comes from Odoo
✅ Portal **NEVER** creates invoices
✅ Portal **syncs** invoices via webhook or scheduler
✅ Portal **saves** invoices to local database
✅ Customer **sees** invoices from local database
✅ Customer **pays** invoices through portal
✅ Payment **recorded** in both portal and Odoo

**Your concern is valid, but the system is already set up correctly!** Invoices come from Odoo, get synced to the portal database, and customers can see and pay them.
