Add price list management across the API, store, services, routes, navigation, and sales views. Support quotes for either a client or a client group, including PDF download and nullable client validation for group-based recipients. Extend client groups to manage assigned clients directly from the form and detail views, and refresh supplier, intervention, stock, and order screens with updated interactions and layouts.
142 lines
5.2 KiB
PHP
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', 'group', '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', 'group', '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(),
|
|
]);
|
|
}
|
|
}
|