feat: agregar relación de proveedor a facturas y actualizar solicitudes y migraciones
This commit is contained in:
parent
8eedb89172
commit
da49a9a75a
@ -20,7 +20,7 @@ class BillController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$query = Bill::query();
|
$query = Bill::query()->with('supplier');
|
||||||
|
|
||||||
if (request()->filled('q')) {
|
if (request()->filled('q')) {
|
||||||
$query->where('name', 'like', '%' . request()->q . '%');
|
$query->where('name', 'like', '%' . request()->q . '%');
|
||||||
@ -108,7 +108,7 @@ public function togglePaid(Bill $bill)
|
|||||||
*/
|
*/
|
||||||
public function export()
|
public function export()
|
||||||
{
|
{
|
||||||
$bills = Bill::where('paid', false)
|
$bills = Bill::with('supplier')->where('paid', false)
|
||||||
->orderBy('deadline')
|
->orderBy('deadline')
|
||||||
->orderBy('created_at')
|
->orderBy('created_at')
|
||||||
->get();
|
->get();
|
||||||
@ -132,14 +132,14 @@ public function export()
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Título
|
// Título
|
||||||
$sheet->mergeCells('A1:E1');
|
$sheet->mergeCells('A1:F1');
|
||||||
$sheet->setCellValue('A1', 'FACTURAS PENDIENTES DE PAGO');
|
$sheet->setCellValue('A1', 'FACTURAS PENDIENTES DE PAGO');
|
||||||
$sheet->getStyle('A1')->applyFromArray([
|
$sheet->getStyle('A1')->applyFromArray([
|
||||||
'font' => ['bold' => true, 'size' => 14],
|
'font' => ['bold' => true, 'size' => 14],
|
||||||
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
|
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$sheet->mergeCells('A2:E2');
|
$sheet->mergeCells('A2:F2');
|
||||||
$sheet->setCellValue('A2', 'Generado el ' . Carbon::now()->format('d/m/Y H:i'));
|
$sheet->setCellValue('A2', 'Generado el ' . Carbon::now()->format('d/m/Y H:i'));
|
||||||
$sheet->getStyle('A2')->applyFromArray([
|
$sheet->getStyle('A2')->applyFromArray([
|
||||||
'font' => ['italic' => true, 'color' => ['rgb' => '666666']],
|
'font' => ['italic' => true, 'color' => ['rgb' => '666666']],
|
||||||
@ -147,11 +147,11 @@ public function export()
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Encabezados
|
// Encabezados
|
||||||
$headers = ['A4' => '#', 'B4' => 'NOMBRE', 'C4' => 'COSTO', 'D4' => 'FECHA LÍMITE', 'E4' => 'DÍAS RESTANTES'];
|
$headers = ['A4' => '#', 'B4' => 'NOMBRE', 'C4' => 'PROVEEDOR', 'D4' => 'COSTO', 'E4' => 'FECHA LÍMITE', 'F4' => 'DÍAS RESTANTES'];
|
||||||
foreach ($headers as $cell => $text) {
|
foreach ($headers as $cell => $text) {
|
||||||
$sheet->setCellValue($cell, $text);
|
$sheet->setCellValue($cell, $text);
|
||||||
}
|
}
|
||||||
$sheet->getStyle('A4:E4')->applyFromArray($styleHeader);
|
$sheet->getStyle('A4:F4')->applyFromArray($styleHeader);
|
||||||
$sheet->getRowDimension(4)->setRowHeight(22);
|
$sheet->getRowDimension(4)->setRowHeight(22);
|
||||||
|
|
||||||
// Datos
|
// Datos
|
||||||
@ -174,26 +174,27 @@ public function export()
|
|||||||
|
|
||||||
$sheet->setCellValue('A' . $row, $i + 1);
|
$sheet->setCellValue('A' . $row, $i + 1);
|
||||||
$sheet->setCellValue('B' . $row, $bill->name);
|
$sheet->setCellValue('B' . $row, $bill->name);
|
||||||
$sheet->setCellValue('C' . $row, (float) $bill->cost);
|
$sheet->setCellValue('C' . $row, $bill->supplier?->business_name ?? '—');
|
||||||
$sheet->setCellValue('D' . $row, $deadline?->format('d/m/Y') ?? '—');
|
$sheet->setCellValue('D' . $row, (float) $bill->cost);
|
||||||
$sheet->setCellValue('E' . $row, $daysLabel);
|
$sheet->setCellValue('E' . $row, $deadline?->format('d/m/Y') ?? '—');
|
||||||
|
$sheet->setCellValue('F' . $row, $daysLabel);
|
||||||
|
|
||||||
$sheet->getStyle('C' . $row)->getNumberFormat()->setFormatCode('$#,##0.00');
|
$sheet->getStyle('D' . $row)->getNumberFormat()->setFormatCode('$#,##0.00');
|
||||||
$sheet->getStyle('A' . $row . ':E' . $row)->applyFromArray($styleData);
|
$sheet->getStyle('A' . $row . ':F' . $row)->applyFromArray($styleData);
|
||||||
$sheet->getStyle('A' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
$sheet->getStyle('A' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
||||||
$sheet->getStyle('C' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT);
|
$sheet->getStyle('D' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT);
|
||||||
$sheet->getStyle('D' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
|
||||||
$sheet->getStyle('E' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
$sheet->getStyle('E' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
||||||
|
$sheet->getStyle('F' . $row)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
|
||||||
|
|
||||||
// Verde si quedan días, rojo si está vencida
|
// Verde si quedan días, rojo si está vencida
|
||||||
if ($daysLeft !== null && $daysLeft > 0) {
|
if ($daysLeft !== null && $daysLeft > 0) {
|
||||||
$sheet->getStyle('E' . $row)->getFont()->getColor()->setRGB('1A7A1A');
|
$sheet->getStyle('F' . $row)->getFont()->getColor()->setRGB('1A7A1A');
|
||||||
} elseif ($daysLeft !== null && $daysLeft < 0) {
|
} elseif ($daysLeft !== null && $daysLeft < 0) {
|
||||||
$sheet->getStyle('D' . $row . ':E' . $row)->getFont()->getColor()->setRGB('CC0000');
|
$sheet->getStyle('E' . $row . ':F' . $row)->getFont()->getColor()->setRGB('CC0000');
|
||||||
$sheet->getStyle('D' . $row . ':E' . $row)->getFont()->setBold(true);
|
$sheet->getStyle('E' . $row . ':F' . $row)->getFont()->setBold(true);
|
||||||
} elseif ($daysLeft === 0) {
|
} elseif ($daysLeft === 0) {
|
||||||
$sheet->getStyle('E' . $row)->getFont()->getColor()->setRGB('B45309');
|
$sheet->getStyle('F' . $row)->getFont()->getColor()->setRGB('B45309');
|
||||||
$sheet->getStyle('E' . $row)->getFont()->setBold(true);
|
$sheet->getStyle('F' . $row)->getFont()->setBold(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$total += (float) $bill->cost;
|
$total += (float) $bill->cost;
|
||||||
@ -201,10 +202,10 @@ public function export()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Total
|
// Total
|
||||||
$sheet->setCellValue('B' . $row, 'TOTAL PENDIENTE');
|
$sheet->setCellValue('C' . $row, 'TOTAL PENDIENTE');
|
||||||
$sheet->setCellValue('C' . $row, $total);
|
$sheet->setCellValue('D' . $row, $total);
|
||||||
$sheet->getStyle('C' . $row)->getNumberFormat()->setFormatCode('$#,##0.00');
|
$sheet->getStyle('D' . $row)->getNumberFormat()->setFormatCode('$#,##0.00');
|
||||||
$sheet->getStyle('B' . $row . ':C' . $row)->applyFromArray([
|
$sheet->getStyle('C' . $row . ':D' . $row)->applyFromArray([
|
||||||
'font' => ['bold' => true, 'size' => 11],
|
'font' => ['bold' => true, 'size' => 11],
|
||||||
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'FFF2CC']],
|
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'FFF2CC']],
|
||||||
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
|
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
|
||||||
@ -213,10 +214,11 @@ public function export()
|
|||||||
|
|
||||||
// Anchos de columna
|
// Anchos de columna
|
||||||
$sheet->getColumnDimension('A')->setWidth(6);
|
$sheet->getColumnDimension('A')->setWidth(6);
|
||||||
$sheet->getColumnDimension('B')->setWidth(40);
|
$sheet->getColumnDimension('B')->setWidth(36);
|
||||||
$sheet->getColumnDimension('C')->setWidth(18);
|
$sheet->getColumnDimension('C')->setWidth(30);
|
||||||
$sheet->getColumnDimension('D')->setWidth(16);
|
$sheet->getColumnDimension('D')->setWidth(18);
|
||||||
$sheet->getColumnDimension('E')->setWidth(16);
|
$sheet->getColumnDimension('E')->setWidth(16);
|
||||||
|
$sheet->getColumnDimension('F')->setWidth(16);
|
||||||
|
|
||||||
// Generar archivo
|
// Generar archivo
|
||||||
$fileName = 'Facturas_Pendientes_' . Carbon::now()->format('Ymd_His') . '.xlsx';
|
$fileName = 'Facturas_Pendientes_' . Carbon::now()->format('Ymd_His') . '.xlsx';
|
||||||
|
|||||||
@ -21,6 +21,7 @@ public function rules(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'supplier_id' => ['nullable', 'exists:suppliers,id'],
|
||||||
'cost' => ['required', 'numeric', 'min:0'],
|
'cost' => ['required', 'numeric', 'min:0'],
|
||||||
'deadline' => ['nullable', 'date'],
|
'deadline' => ['nullable', 'date'],
|
||||||
'paid' => ['boolean'],
|
'paid' => ['boolean'],
|
||||||
@ -35,6 +36,7 @@ public function messages(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name.required' => 'El nombre de la factura es obligatorio.',
|
'name.required' => 'El nombre de la factura es obligatorio.',
|
||||||
|
'supplier_id.exists' => 'El proveedor seleccionado no es válido.',
|
||||||
'cost.required' => 'El costo es obligatorio.',
|
'cost.required' => 'El costo es obligatorio.',
|
||||||
'cost.numeric' => 'El costo debe ser un número válido.',
|
'cost.numeric' => 'El costo debe ser un número válido.',
|
||||||
'cost.min' => 'El costo debe ser un valor positivo.',
|
'cost.min' => 'El costo debe ser un valor positivo.',
|
||||||
|
|||||||
@ -21,6 +21,7 @@ public function rules(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'supplier_id' => ['nullable', 'exists:suppliers,id'],
|
||||||
'cost' => ['required', 'numeric', 'min:0'],
|
'cost' => ['required', 'numeric', 'min:0'],
|
||||||
'deadline' => ['nullable', 'date'],
|
'deadline' => ['nullable', 'date'],
|
||||||
'paid' => ['boolean'],
|
'paid' => ['boolean'],
|
||||||
@ -35,6 +36,7 @@ public function messages(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name.required' => 'El nombre de la factura es obligatorio.',
|
'name.required' => 'El nombre de la factura es obligatorio.',
|
||||||
|
'supplier_id.exists' => 'El proveedor seleccionado no es válido.',
|
||||||
'cost.required' => 'El costo es obligatorio.',
|
'cost.required' => 'El costo es obligatorio.',
|
||||||
'cost.numeric' => 'El costo debe ser un número válido.',
|
'cost.numeric' => 'El costo debe ser un número válido.',
|
||||||
'cost.min' => 'El costo debe ser un valor positivo.',
|
'cost.min' => 'El costo debe ser un valor positivo.',
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class Bill extends Model
|
|||||||
{
|
{
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
|
'supplier_id',
|
||||||
'cost',
|
'cost',
|
||||||
'file_path',
|
'file_path',
|
||||||
'deadline',
|
'deadline',
|
||||||
@ -23,6 +24,11 @@ class Bill extends Model
|
|||||||
|
|
||||||
protected $appends = ['file_url'];
|
protected $appends = ['file_url'];
|
||||||
|
|
||||||
|
public function supplier()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Supplier::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function getFileUrlAttribute(): ?string
|
public function getFileUrlAttribute(): ?string
|
||||||
{
|
{
|
||||||
if (!$this->file_path) return null;
|
if (!$this->file_path) return null;
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('bills', function (Blueprint $table) {
|
||||||
|
$table->foreignId('supplier_id')->after('name')->nullable()->constrained('suppliers')->nullOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('bills', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['supplier_id']);
|
||||||
|
$table->dropColumn('supplier_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user