# Odoo Payment Workflow

## How Odoo Handles Payments (What We're Matching)

### Odoo's Standard Payment Flow

```
1. Quotation (sale.order in draft)
   ↓
2. Confirm Order (state: 'sale')
   ↓
3. Create Invoice (account.move)
   ↓
4. Post Invoice (state: 'posted')
   ↓
5. Register Payment (account.payment)
   ↓
6. Reconcile Payment with Invoice
   ↓
7. Invoice marked as paid (payment_state: 'paid')
```

### Our Portal Implementation Matches This

```
1. Quotation accepted in portal
   ↓
2. Sales order created in Odoo (auto-confirmed)
   ↓
3. Invoice generated in Odoo (auto-posted)
   ↓
4. Customer pays via portal (Pesepay or Bank Transfer)
   ↓
5. Portal records payment in Odoo
   ↓
6. Odoo reconciles payment automatically
   ↓
7. Invoice payment_state → 'paid' ✓
```

## Odoo Models & Fields Updated

### 1. account.move (Invoice)

**Before Payment:**
```python
{
    'id': 888,
    'name': 'INV/2024/0001',
    'move_type': 'out_invoice',
    'state': 'posted',
    'payment_state': 'not_paid',  # ← Not paid yet
    'amount_total': 150.00,
    'amount_residual': 150.00,    # ← Full amount due
    'invoice_date': '2024-02-15',
    'invoice_date_due': '2024-03-15',
    'partner_id': 42,
}
```

**After Payment:**
```python
{
    'id': 888,
    'name': 'INV/2024/0001',
    'move_type': 'out_invoice',
    'state': 'posted',
    'payment_state': 'paid',      # ← UPDATED: Now paid
    'amount_total': 150.00,
    'amount_residual': 0.00,      # ← UPDATED: No balance
    'invoice_date': '2024-02-15',
    'invoice_date_due': '2024-03-15',
    'partner_id': 42,
}
```

### 2. account.payment (Payment Record)

**Created by Portal:**
```python
{
    'id': 999,  # New payment record
    'name': 'PAY/2024/0001',
    'partner_id': 42,
    'amount': 150.00,
    'payment_type': 'inbound',
    'partner_type': 'customer',
    'payment_method_line_id': 1,  # Bank/Cash method
    'date': '2024-02-15',
    'ref': 'PAY-123456',  # Our portal reference
    'communication': 'Payment via Pesepay - PESE-789',
    'state': 'posted',  # Posted automatically
}
```

### 3. account.move.line (Journal Entries)

**Automatic Journal Entries Created:**
```python
# Debit Entry (Bank Account)
{
    'account_id': 100,  # Bank account
    'debit': 150.00,
    'credit': 0.00,
    'partner_id': 42,
}

# Credit Entry (Accounts Receivable)
{
    'account_id': 200,  # AR account
    'debit': 0.00,
    'credit': 150.00,
    'partner_id': 42,
}
```

### 4. sale.order (Sales Order)

**Before Payment:**
```python
{
    'id': 777,
    'name': 'SO001',
    'state': 'draft',  # or 'sent'
    'invoice_status': 'to invoice',
}
```

**After Payment:**
```python
{
    'id': 777,
    'name': 'SO001',
    'state': 'sale',  # ← UPDATED: Confirmed
    'invoice_status': 'invoiced',  # ← UPDATED: Invoiced
}
```

## Odoo API Calls Made by Portal

### Call 1: Record Payment
```php
// OdooService::recordPayment()
$paymentId = $odooService->call('account.payment', 'create', [
    'partner_id' => 42,
    'amount' => 150.00,
    'payment_type' => 'inbound',
    'partner_type' => 'customer',
    'date' => '2024-02-15',
    'ref' => 'PAY-123456',
    'communication' => 'Payment via Pesepay',
]);
// Returns: 999 (new payment ID)
```

### Call 2: Post Payment
```php
// Makes payment official
$odooService->call('account.payment', 'action_post', [999]);
// Payment state changes from 'draft' to 'posted'
```

### Call 3: Confirm Sales Order
```php
// Confirms the order
$odooService->call('sale.order', 'action_confirm', [777]);
// Order state changes from 'draft' to 'sale'
```

### Call 4: Get Payment Status (Verification)
```php
// Check if payment was successful
$status = $odooService->getPaymentStatus(888);
// Returns:
[
    'invoice' => [...],
    'payments' => [...],
    'total_paid' => 150.00,
    'amount_due' => 0.00,
    'is_paid' => true,
]
```

## Odoo Reconciliation Process

### What is Reconciliation?
Matching payments with invoices to mark them as paid.

### Automatic Reconciliation
When we create a payment with the correct invoice reference, Odoo automatically:

1. **Finds matching invoice** by partner_id and amount
2. **Creates reconciliation** between payment and invoice
3. **Updates invoice** payment_state to 'paid'
4. **Clears amount_residual** to 0

### Manual Reconciliation (if needed)
If automatic reconciliation fails:

```python
# In Odoo UI:
Accounting → Customers → Payments
→ Select payment
→ Click "Reconcile"
→ Match with invoice
```

## Odoo Payment States

### Invoice Payment States
- `not_paid` - No payment received
- `in_payment` - Payment in progress
- `paid` - ✅ Fully paid
- `partial` - Partially paid
- `reversed` - Payment reversed
- `invoicing_legacy` - Legacy state

### Payment States
- `draft` - Payment created but not posted
- `posted` - ✅ Payment posted (official)
- `sent` - Payment sent to bank
- `reconciled` - ✅ Matched with invoice
- `cancelled` - Payment cancelled

### Order States
- `draft` - Order being prepared
- `sent` - Quotation sent to customer
- `sale` - ✅ Order confirmed
- `done` - Order completed
- `cancel` - Order cancelled

## Odoo Accounting Impact

### Chart of Accounts Affected

**When Payment is Recorded:**

| Account | Type | Debit | Credit |
|---------|------|-------|--------|
| Bank Account | Asset | $150.00 | - |
| Accounts Receivable | Asset | - | $150.00 |

**Result:**
- Bank balance increases by $150
- AR balance decreases by $150
- Customer balance becomes $0

### Financial Reports Updated
- **Balance Sheet**: Bank account increases, AR decreases
- **Profit & Loss**: Revenue already recorded when invoice posted
- **Cash Flow**: Cash inflow recorded
- **Aged Receivables**: Customer removed from aging report

## Odoo Notifications (If Configured)

Odoo can send automatic notifications:

1. **Payment Received** - Email to accounting team
2. **Invoice Paid** - Email to customer
3. **Order Confirmed** - Email to sales team
4. **Delivery Order** - Email to warehouse

Our portal handles customer notifications separately.

## Odoo Workflow Automation

### Automated Actions in Odoo

**When Invoice is Paid:**
- ✅ Update order status
- ✅ Trigger delivery order creation
- ✅ Send confirmation emails
- ✅ Update customer credit limit
- ✅ Generate accounting entries

**When Order is Confirmed:**
- ✅ Reserve inventory (if applicable)
- ✅ Create delivery orders
- ✅ Schedule installation
- ✅ Notify operations team

## Comparison: Portal vs Odoo

### What Portal Does
1. ✅ Collects payment from customer
2. ✅ Records payment in portal database
3. ✅ Sends payment data to Odoo
4. ✅ Updates portal entities (invoice, order, quotation)
5. ✅ Sends customer notifications

### What Odoo Does
1. ✅ Receives payment data from portal
2. ✅ Creates account.payment record
3. ✅ Posts payment to accounting
4. ✅ Reconciles with invoice
5. ✅ Updates invoice payment_state
6. ✅ Confirms sales order
7. ✅ Triggers workflow automation

### Division of Responsibility

| Task | Portal | Odoo |
|------|--------|------|
| Payment collection | ✅ | - |
| Payment gateway integration | ✅ | - |
| Customer notifications | ✅ | - |
| Payment recording | ✅ | ✅ |
| Invoice management | ✅ | ✅ |
| Accounting entries | - | ✅ |
| Financial reporting | - | ✅ |
| Order fulfillment | - | ✅ |

## Error Scenarios & Handling

### Scenario 1: Odoo Connection Lost
```
Portal: Payment completed ✓
Portal: Invoice marked as paid ✓
Odoo: Connection failed ✗

Action:
- Portal updates succeed
- Error logged
- Manual sync later
- Customer still gets confirmation
```

### Scenario 2: Payment Already Exists in Odoo
```
Portal: Tries to record payment
Odoo: Payment already exists (duplicate)

Action:
- Portal catches error
- Verifies payment status
- Continues if already paid
- Logs warning
```

### Scenario 3: Invoice Not Found in Odoo
```
Portal: Payment completed
Odoo: Invoice ID not found

Action:
- Portal updates succeed
- Error logged
- Admin notified
- Manual reconciliation needed
```

## Verification Checklist

After payment, verify in Odoo:

### Invoice Check
```
Accounting → Customers → Invoices
→ Find invoice INV/2024/0001
→ Check payment_state = 'paid' ✓
→ Check amount_residual = 0.00 ✓
```

### Payment Check
```
Accounting → Customers → Payments
→ Find payment PAY/2024/0001
→ Check state = 'posted' ✓
→ Check reconciled with invoice ✓
```

### Order Check
```
Sales → Orders
→ Find order SO001
→ Check state = 'sale' ✓
→ Check invoice_status = 'invoiced' ✓
```

### Customer Balance Check
```
Accounting → Customers → Customer
→ Find customer
→ Check balance = 0.00 ✓
```

## Summary

Our portal implementation **fully matches Odoo's standard payment workflow**:

1. ✅ Creates proper account.payment records
2. ✅ Posts payments correctly
3. ✅ Reconciles with invoices automatically
4. ✅ Updates invoice payment_state
5. ✅ Confirms sales orders
6. ✅ Maintains accounting integrity
7. ✅ Triggers Odoo workflow automation

**Result:** Seamless integration between portal and Odoo with complete financial accuracy.
