153 lines
6.3 KiB
PHP
153 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\Client;
|
|
use App\Models\Invoice;
|
|
use App\Models\InvoiceLine;
|
|
use App\Models\Quote;
|
|
use Illuminate\Database\Seeder;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class InvoiceSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$clientIds = Client::pluck('id')->toArray();
|
|
$products = DB::table('products')->select('id', 'prix_unitaire')->get()->keyBy('id');
|
|
$productIds = $products->keys()->toArray();
|
|
|
|
if (empty($clientIds) || empty($productIds)) {
|
|
$this->command->warn('InvoiceSeeder: aucun client ou produit trouvé — skip.');
|
|
return;
|
|
}
|
|
|
|
// ── 1. Invoices liées à des devis acceptés ────────────────────────────
|
|
$acceptedQuotes = Quote::where('status', 'accepte')
|
|
->orderBy('id')
|
|
->limit(35)
|
|
->get();
|
|
|
|
foreach ($acceptedQuotes as $quote) {
|
|
$invoiceDate = $quote->quote_date->copy()->addDays(rand(2, 10))->format('Y-m-d');
|
|
$dueDate = date('Y-m-d', strtotime($invoiceDate . ' +30 days'));
|
|
|
|
// Statuses for quote-linked invoices (mostly paid)
|
|
$s = ['payee', 'payee', 'payee', 'emise', 'envoyee', 'partiellement_payee'];
|
|
|
|
Invoice::create([
|
|
'client_id' => $quote->client_id,
|
|
'source_quote_id' => $quote->id,
|
|
'status' => $s[array_rand($s)],
|
|
'invoice_date' => $invoiceDate,
|
|
'due_date' => $dueDate,
|
|
'currency' => 'EUR',
|
|
'total_ht' => $quote->total_ht,
|
|
'total_tva' => $quote->total_tva,
|
|
'total_ttc' => $quote->total_ttc,
|
|
]);
|
|
// Lines are not duplicated — source quote already has them
|
|
}
|
|
|
|
// ── 2. Invoices autonomes ─────────────────────────────────────────────
|
|
// 2024 historical — statuses varied, many paid
|
|
$this->createBatch($clientIds, $productIds, $products, [
|
|
'yearRange' => [[2024, 1, 12]],
|
|
'countPerMonth' => [3, 5],
|
|
'statusPool' => ['payee', 'payee', 'payee', 'emise', 'envoyee', 'partiellement_payee', 'echue'],
|
|
]);
|
|
|
|
// 2025 main year — rich dataset
|
|
$this->createBatch($clientIds, $productIds, $products, [
|
|
'yearRange' => [[2025, 1, 12]],
|
|
'countPerMonth' => [4, 7],
|
|
'statusPool' => ['payee', 'payee', 'payee', 'emise', 'envoyee', 'partiellement_payee', 'echue', 'echue'],
|
|
]);
|
|
|
|
// 2026 Jan-Apr — no echue (due dates not yet past)
|
|
$this->createBatch($clientIds, $productIds, $products, [
|
|
'yearRange' => [[2026, 1, 4]],
|
|
'countPerMonth' => [4, 6],
|
|
'statusPool' => ['payee', 'payee', 'emise', 'envoyee', 'partiellement_payee'],
|
|
]);
|
|
|
|
// 2026 May 1-8 — recent, mostly emise
|
|
$this->createBatch($clientIds, $productIds, $products, [
|
|
'yearRange' => [[2026, 5, 5]],
|
|
'countPerMonth' => [4, 6],
|
|
'maxDay' => 8,
|
|
'statusPool' => ['payee', 'emise', 'emise', 'envoyee'],
|
|
]);
|
|
|
|
$total = Invoice::count();
|
|
$this->command->info("InvoiceSeeder: {$total} factures au total.");
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
private function createBatch(
|
|
array $clientIds,
|
|
array $productIds,
|
|
\Illuminate\Support\Collection $products,
|
|
array $opts
|
|
): void {
|
|
foreach ($opts['yearRange'] as [$year, $startM, $endM]) {
|
|
for ($m = $startM; $m <= $endM; $m++) {
|
|
$maxDay = $opts['maxDay'] ?? 28;
|
|
$count = rand(...$opts['countPerMonth']);
|
|
|
|
for ($i = 0; $i < $count; $i++) {
|
|
$invoiceDate = sprintf('%04d-%02d-%02d', $year, $m, rand(1, $maxDay));
|
|
$status = $opts['statusPool'][array_rand($opts['statusPool'])];
|
|
|
|
// due_date
|
|
if ($status === 'echue') {
|
|
$dueDate = date('Y-m-d', strtotime($invoiceDate . ' +10 days'));
|
|
} else {
|
|
$dueDate = date('Y-m-d', strtotime($invoiceDate . ' +30 days'));
|
|
}
|
|
|
|
$clientId = $clientIds[array_rand($clientIds)];
|
|
|
|
// Build lines
|
|
$lineData = [];
|
|
$totalHt = 0.0;
|
|
for ($l = 0, $nl = rand(1, 3); $l < $nl; $l++) {
|
|
$pid = $productIds[array_rand($productIds)];
|
|
$unitPrice = (float) ($products->get($pid)->prix_unitaire ?? 150.00);
|
|
$qty = rand(1, 3);
|
|
$lineHt = round($unitPrice * $qty, 2);
|
|
$totalHt += $lineHt;
|
|
$lineData[] = [
|
|
'product_id' => $pid,
|
|
'description' => 'Prestation funéraire',
|
|
'qty_base' => $qty,
|
|
'unit_price' => $unitPrice,
|
|
'discount_pct' => 0,
|
|
'total_ht' => $lineHt,
|
|
];
|
|
}
|
|
|
|
$totalTva = round($totalHt * 0.20, 2);
|
|
$totalTtc = round($totalHt + $totalTva, 2);
|
|
|
|
$invoice = Invoice::create([
|
|
'client_id' => $clientId,
|
|
'status' => $status,
|
|
'invoice_date' => $invoiceDate,
|
|
'due_date' => $dueDate,
|
|
'currency' => 'EUR',
|
|
'total_ht' => $totalHt,
|
|
'total_tva' => $totalTva,
|
|
'total_ttc' => $totalTtc,
|
|
]);
|
|
|
|
foreach ($lineData as $line) {
|
|
InvoiceLine::create(array_merge($line, ['invoice_id' => $invoice->id]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|