# RealGreen API Integration Package

## Overview
This package provides integration with the RealGreen CRM system, automatically exporting estimates to their API when they're updated. It handles data transformation from Bongo estimate models to RealGreen's lead form format.

## Project Structure

```
src/
├── Commands/
│   └── ExportEstimatesToRealGreen.php    # CLI command for batch exports
├── Config/
│   └── realgreen.php                     # API configuration
├── Data/
│   └── LeadFormData.php                  # DTO for RealGreen lead form
├── Listeners/
│   └── ExportEstimateToRealGreen.php     # Event listener for real-time exports
├── Schema/
│   └── lead_form.json                    # Example payload structure
├── Seeders/
│   └── PackageSeeder.php                 # Package registration
├── Services/
│   ├── LeadForm.php                      # Lead form export service
│   └── SourceCode.php                    # Marketing source code service
└── RealGreenServiceProvider.php          # Service provider
```

## Architecture

### Service Provider Pattern
This package extends `Bongo\Framework\Providers\AbstractServiceProvider` which provides automatic bootstrapping:

```php
class RealGreenServiceProvider extends AbstractServiceProvider
{
    protected string $module = 'realgreen';

    // Auto-registers console commands
    protected array $commands = [
        ExportEstimatesToRealGreen::class,
    ];

    // Auto-registers event listeners
    protected array $listeners = [
        EstimateUpdated::class => [
            ExportEstimateToRealGreen::class,
        ],
    ];
}
```

The `$module` property automatically loads:
- Config from `src/Config/realgreen.php`
- No routes (this package is API integration only)
- No views, migrations, or translations

### Event-Driven Architecture
The package listens for `EstimateUpdated` events and automatically exports to RealGreen when:
- The application is in production mode
- The RealGreen API key is configured
- The estimate is not in DRAFT status

### Data Transfer Object Pattern
`LeadFormData` is a DTO that:
- Maps Bongo estimate model fields to RealGreen API structure
- Handles data validation and transformation
- Provides fallback values for required fields

### Service Layer
Two services handle API communication:
- `LeadForm`: Exports estimate data to RealGreen's lead form endpoint
- `SourceCode`: Retrieves marketing source codes from RealGreen

## Key Classes and Responsibilities

### Commands/ExportEstimatesToRealGreen.php
CLI command for batch exporting estimates to RealGreen.

**Signature**: `realgreen:export_estimates {--all}`

**Options**:
- `--all`: Export all non-draft estimates (including previously exported)

**Behaviour**:
- Checks for API key configuration
- Queries estimates that need exporting
- Updates `exported_at` timestamp on success
- Records errors in `export_error` field
- Continues processing on failure (doesn't abort batch)

### Data/LeadFormData.php
Data transfer object that transforms estimate data for RealGreen API.

**Key Methods**:
- `fromModel(Estimate $estimate): self` - Populates DTO from estimate model
- `toArray(): array` - Converts to RealGreen API payload format

**Field Mapping**:
- `name`: Estimate number with optional customer name
- `streetNumberAndName`: Combined line_1 and line_2
- `zipcode`/`zip`: Postcode with spaces removed
- `emailAddress`: Customer email
- `cellPhoneNumber`: Customer phone
- `firstName`/`lastName`: Customer name components
- `sourceCode`: Marketing source from config (default: 28 for "GOO")
- `callLogNotes`: Formatted estimate details (areas, totals, payment info)
- `employeeID`: Fixed to "JCHAPMAN"
- `actionReasonID`: Fixed to 18 (Note type in RealGreen)

**Fallback Values**:
- Uses `'-- --'` for required address fields when empty
- Uses `null` for optional fields when empty

### Services/LeadForm.php
Handles HTTP communication with RealGreen's lead form submission endpoint.

**Key Method**: `export(Estimate $estimate): ?array`
- Creates `LeadFormData` from estimate
- POSTs to `/LeadForm/Submit` endpoint
- Uses `apiKey` header authentication
- Disables SSL verification (withoutVerifying)
- Throws RequestException on HTTP errors

### Services/SourceCode.php
Retrieves marketing source codes from RealGreen API.

**Key Methods**:
- `all(): Collection` - Fetches all source codes
- `byAbbreviation(string $abbreviation): ?array` - Finds source code by abbreviation

### Listeners/ExportEstimateToRealGreen.php
Event listener that automatically exports estimates on update.

**Trigger Conditions**:
- `app()->isProduction()` must be true
- `setting('system::credentials.real_green_api_key')` must be set
- Estimate must not be in DRAFT status

**Error Handling**:
- Catches `RequestException` and `BindingResolutionException`
- Logs exceptions using `log_exception()` helper
- Prints to console using `console_print()` helper
- Stores error message in `estimate.export_error` field
- Doesn't rethrow (fails silently to prevent blocking estimate updates)

## Configuration

### Config/realgreen.php

```php
return [
    // API base URL
    'api_url' => env('REALGREEN_API_URL', 'https://saapi.realgreen.com'),

    // Marketing source code (28 = GOO/Google)
    'source_code' => 28,
];
```

### Required Environment Variables

```bash
# RealGreen API base URL (optional, defaults to production)
REALGREEN_API_URL=https://saapi.realgreen.com

# RealGreen API key (stored in system settings)
# Access via: setting('system::credentials.real_green_api_key')
```

## Coding Conventions

### Strict Types
All PHP files use `declare(strict_types=1);`

### Return Type Declarations
All methods have explicit return types:
```php
public function export(Estimate $estimate): ?array
public function handle(): void
```

### Exception Handling
Methods that may throw exceptions document them in PHPDoc:
```php
/** @throws RequestException|BindingResolutionException */
public function export(Estimate $estimate): ?array
```

### Code Style
Uses Laravel Pint with custom rules:
- Laravel preset
- No parentheses for `new` statements
- No nullable type declarations for default null values
- Strict types enabled
- Parentheses required for declare statements

Run: `vendor/bin/pint` or `composer format`

## Common Tasks

### Adding a New Field to Export

1. Add property to `Data/LeadFormData.php`:
```php
public ?string $newField;
```

2. Add setter method:
```php
protected function setNewField(Estimate $estimate): void
{
    $this->newField = $estimate->new_field ?? null;
}
```

3. Call setter in `fromModel()`:
```php
$this->setNewField($estimate);
```

4. Add to `toArray()`:
```php
return [
    // ... existing fields
    'newField' => $this->newField,
];
```

### Testing Export Manually

```bash
# Export all non-exported estimates
php artisan realgreen:export_estimates

# Re-export all estimates (including previously exported)
php artisan realgreen:export_estimates --all
```

### Checking for Export Errors

Errors are stored in the `export_error` column of the estimate model:
```php
$estimate = Estimate::find($id);
if ($estimate->export_error) {
    // Handle error
}
```

### Retrieving Source Codes

```php
use Bongo\RealGreen\Services\SourceCode;

// Get all source codes
$sourceCodes = (new SourceCode())->all();

// Find by abbreviation
$googleSource = (new SourceCode())->byAbbreviation('GOO');
```

## Testing

### Running Tests
```bash
composer test
# or
vendor/bin/phpunit
```

### Test Coverage
```bash
composer test-coverage
```

### Code Analysis
```bash
composer analyse
# or
vendor/bin/phpstan analyse
```

## Dependencies

### Required Packages
- `bongo/framework` (^3.0): Provides AbstractServiceProvider and core utilities
- `bongo/estimate`: Provides Estimate model and EstimateUpdated event
- `illuminate/contracts` (^10.0): Laravel framework contracts

### Helper Functions Used
- `setting()`: Retrieves system settings
- `log_exception()`: Logs exceptions to Laravel log
- `console_print()`: Outputs to console in command context

## API Integration Details

### RealGreen API Endpoints

**Base URL**: `https://saapi.realgreen.com`

**Authentication**: Header-based API key
```php
'apiKey' => setting('system::credentials.real_green_api_key')
```

**Endpoints Used**:
- `POST /LeadForm/Submit`: Submit new lead form
- `GET /SourceCode`: Retrieve marketing source codes

### SSL Verification
The package uses `withoutVerifying()` to disable SSL certificate verification. This may be required for staging environments but should be reviewed for production security.

## Troubleshooting

### Exports Not Happening
Check these conditions:
1. Is `app()->isProduction()` true?
2. Is API key set: `setting('system::credentials.real_green_api_key')`
3. Is estimate status not DRAFT?
4. Check `estimate.export_error` field for error messages

### Manual Export for Testing
Use the command with specific estimate IDs by modifying the query:
```php
// In ExportEstimatesToRealGreen.php
$estimates = Estimate::whereIn('id', [1, 2, 3])->get();
```

### Debugging API Requests
Add logging to `Services/LeadForm.php`:
```php
\Log::debug('RealGreen Export', $leadFormData);
```

## Related Documentation
- See `ARCHITECTURE.md` for detailed architecture diagrams
- See `README.md` for installation instructions
- See `CLAUDE.md` for quick reference
