2026-01-12 16:37:41 +03:00

142 lines
5.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Repositories;
use App\Models\Quote;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Repositories\ClientActivityTimelineRepositoryInterface;
class QuoteRepository extends BaseRepository implements QuoteRepositoryInterface
{
public function __construct(
Quote $model,
protected QuoteLineRepositoryInterface $quoteLineRepository,
protected InvoiceRepositoryInterface $invoiceRepository,
protected readonly ClientActivityTimelineRepositoryInterface $timelineRepository
) {
parent::__construct($model);
}
public function all(array $columns = ['*']): \Illuminate\Support\Collection
{
return $this->model->with(['client', 'lines.product'])->get($columns);
}
public function create(array $data): Quote
{
return DB::transaction(function () use ($data) {
try {
// Create the quote
$quote = parent::create($data);
// Create the quote lines
if (isset($data['lines']) && is_array($data['lines'])) {
foreach ($data['lines'] as $lineData) {
$lineData['quote_id'] = $quote->id;
$this->quoteLineRepository->create($lineData);
}
}
// Record initial status history
$this->recordHistory($quote->id, null, $quote->status, 'Quote created');
try {
$this->timelineRepository->logActivity([
'client_id' => $quote->client_id,
'actor_type' => 'user',
'actor_user_id' => auth()->id(),
'event_type' => 'quote_created',
'entity_type' => 'quote',
'entity_id' => $quote->id,
'title' => 'Nouveau devis créé',
'description' => "Le devis #{$quote->id} a été créé.",
'created_at' => now(),
]);
} catch (\Exception $e) {
Log::error("Failed to log quote creation activity: " . $e->getMessage());
}
return $quote;
} catch (\Exception $e) {
Log::error('Error creating quote with lines: ' . $e->getMessage(), [
'exception' => $e,
'data' => $data,
]);
throw $e;
}
});
}
public function update(int|string $id, array $attributes): bool
{
return DB::transaction(function () use ($id, $attributes) {
try {
$quote = $this->find($id);
if (!$quote) {
return false;
}
$oldStatus = $quote->status;
// Update the quote
$updated = parent::update($id, $attributes);
if ($updated) {
$newStatus = $attributes['status'] ?? $oldStatus;
// If status changed, record history
if ($oldStatus !== $newStatus) {
$this->recordHistory((int) $id, $oldStatus, $newStatus, 'Quote status updated');
// Auto-create invoice when status changes to 'accepte'
if ($newStatus === 'accepte' && $oldStatus !== 'accepte') {
try {
$this->invoiceRepository->createFromQuote($id);
Log::info('Invoice auto-created from quote', ['quote_id' => $id]);
} catch (\Exception $e) {
Log::error('Failed to auto-create invoice from quote: ' . $e->getMessage(), [
'quote_id' => $id,
'exception' => $e,
]);
// Don't throw - quote update should still succeed
}
}
}
}
return $updated;
} catch (\Exception $e) {
Log::error('Error updating quote: ' . $e->getMessage(), [
'id' => $id,
'attributes' => $attributes,
'exception' => $e,
]);
throw $e;
}
});
}
public function find(int|string $id, array $columns = ['*']): ?Quote
{
return $this->model->with(['client', 'lines.product', 'history.user'])->find($id, $columns);
}
private function recordHistory(int $quoteId, ?string $oldStatus, string $newStatus, ?string $comment = null): void
{
\App\Models\DocumentStatusHistory::create([
'document_type' => 'quote',
'document_id' => $quoteId,
'old_status' => $oldStatus,
'new_status' => $newStatus,
'changed_by' => auth()->id(), // Assuming authenticated user
'comment' => $comment,
'changed_at' => now(),
]);
}
}