added download button for orignal import csv file
This commit is contained in:
parent
2968bcf3f8
commit
9cc1b7072c
|
|
@ -9,7 +9,6 @@
|
|||
use App\Models\ImportEvent;
|
||||
use App\Models\ImportTemplate;
|
||||
use App\Services\CsvImportService;
|
||||
use App\Services\Import\ImportServiceV2;
|
||||
use App\Services\Import\ImportSimulationServiceV2;
|
||||
use App\Services\ImportProcessor;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -190,6 +189,7 @@ public function process(Import $import, Request $request, ImportProcessor $proce
|
|||
|
||||
try {
|
||||
$result = $processor->process($import, user: $request->user());
|
||||
|
||||
return response()->json($result);
|
||||
} catch (\Throwable $e) {
|
||||
\Log::error('Import processing failed', [
|
||||
|
|
@ -712,8 +712,6 @@ public function simulatePayments(Import $import, Request $request)
|
|||
* templates. For payments templates, payment-specific summaries/entities will be included
|
||||
* automatically by the simulation service when mappings contain the payment root.
|
||||
*
|
||||
* @param Import $import
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function simulate(Import $import, Request $request)
|
||||
|
|
@ -829,4 +827,19 @@ public function destroy(Request $request, Import $import)
|
|||
|
||||
return back()->with('success', 'Import deleted successfully');
|
||||
}
|
||||
|
||||
// Download the original import file
|
||||
public function download(Import $import)
|
||||
{
|
||||
// Verify file exists
|
||||
if (! $import->disk || ! $import->path || ! Storage::disk($import->disk)->exists($import->path)) {
|
||||
return response()->json([
|
||||
'error' => 'File not found',
|
||||
], 404);
|
||||
}
|
||||
|
||||
$fileName = $import->original_name ?? 'import_'.$import->uuid;
|
||||
|
||||
return Storage::disk($import->disk)->download($import->path, $fileName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1094,6 +1094,16 @@ async function fetchEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
async function downloadImport() {
|
||||
if (!importId.value) return;
|
||||
try {
|
||||
const url = route("imports.download", { import: importId.value });
|
||||
window.location.href = url;
|
||||
} catch (e) {
|
||||
console.error("Download failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Simulation (generic or payments) state
|
||||
const showPaymentSim = ref(false);
|
||||
const paymentSimLoading = ref(false);
|
||||
|
|
@ -1339,6 +1349,7 @@ async function fetchSimulation() {
|
|||
:can-process="canProcess"
|
||||
:selected-mappings-count="selectedMappingsCount"
|
||||
@preview="openPreview"
|
||||
@download="downloadImport"
|
||||
@save-mappings="saveMappings"
|
||||
@process-import="processImport"
|
||||
@simulate="openSimulation"
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import {
|
|||
ArrowPathIcon,
|
||||
BeakerIcon,
|
||||
ArrowDownOnSquareIcon,
|
||||
ArrowDownTrayIcon,
|
||||
} from "@heroicons/vue/24/outline";
|
||||
import { Button } from '@/Components/ui/button';
|
||||
import { Badge } from '@/Components/ui/badge';
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Badge } from "@/Components/ui/badge";
|
||||
|
||||
const props = defineProps({
|
||||
importId: [Number, String],
|
||||
|
|
@ -16,15 +17,30 @@ const props = defineProps({
|
|||
canProcess: Boolean,
|
||||
selectedMappingsCount: Number,
|
||||
});
|
||||
const emits = defineEmits(["preview", "save-mappings", "process-import", "simulate"]);
|
||||
const emits = defineEmits([
|
||||
"preview",
|
||||
"save-mappings",
|
||||
"process-import",
|
||||
"simulate",
|
||||
"download",
|
||||
]);
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex flex-wrap gap-2 items-center" v-if="!isCompleted">
|
||||
<div class="flex flex-wrap gap-2 items-center">
|
||||
<!-- Download button - always visible -->
|
||||
<Button
|
||||
variant="secondary"
|
||||
@click.prevent="$emit('preview')"
|
||||
@click.prevent="$emit('download')"
|
||||
:disabled="!importId"
|
||||
title="Preznesi originalno uvozno datoteko"
|
||||
>
|
||||
<ArrowDownTrayIcon class="h-4 w-4 mr-2" />
|
||||
Presnemi datoteko
|
||||
</Button>
|
||||
|
||||
<!-- Other action buttons - only when not completed -->
|
||||
<div class="flex flex-wrap gap-2 items-center" v-if="!isCompleted">
|
||||
<Button variant="secondary" @click.prevent="$emit('preview')" :disabled="!importId">
|
||||
<EyeIcon class="h-4 w-4 mr-2" />
|
||||
Predogled vrstic
|
||||
</Button>
|
||||
|
|
@ -41,11 +57,9 @@ const emits = defineEmits(["preview", "save-mappings", "process-import", "simula
|
|||
></span>
|
||||
<ArrowPathIcon v-else class="h-4 w-4 mr-2" />
|
||||
<span>Shrani preslikave</span>
|
||||
<Badge
|
||||
v-if="selectedMappingsCount"
|
||||
variant="secondary"
|
||||
class="ml-2 text-xs"
|
||||
>{{ selectedMappingsCount }}</Badge>
|
||||
<Badge v-if="selectedMappingsCount" variant="secondary" class="ml-2 text-xs">{{
|
||||
selectedMappingsCount
|
||||
}}</Badge>
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
|
|
@ -66,4 +80,5 @@ const emits = defineEmits(["preview", "save-mappings", "process-import", "simula
|
|||
Simulacija vnosa
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@
|
|||
Route::get('imports/{import}/missing-keyref-rows', [ImportController::class, 'missingKeyrefRows'])->name('imports.missing-keyref-rows');
|
||||
Route::get('imports/{import}/missing-keyref-csv', [ImportController::class, 'exportMissingKeyrefCsv'])->name('imports.missing-keyref-csv');
|
||||
Route::get('imports/{import}/preview', [ImportController::class, 'preview'])->name('imports.preview');
|
||||
Route::get('imports/{import}/download', [ImportController::class, 'download'])->name('imports.download');
|
||||
Route::get('imports/{import}/missing-contracts', [ImportController::class, 'missingContracts'])->name('imports.missing-contracts');
|
||||
Route::post('imports/{import}/options', [ImportController::class, 'updateOptions'])->name('imports.options');
|
||||
// Generic simulation endpoint (new) – provides projected effects for first N rows regardless of payments template
|
||||
|
|
|
|||
72
tests/Feature/ImportDownloadTest.php
Normal file
72
tests/Feature/ImportDownloadTest.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Import;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
it('downloads the original import file', function () {
|
||||
// Create a test file
|
||||
$uuid = (string) Str::uuid();
|
||||
$disk = 'local';
|
||||
$path = "imports/{$uuid}.csv";
|
||||
$csv = "email,reference\nalpha@example.com,REF-1\n";
|
||||
Storage::disk($disk)->put($path, $csv);
|
||||
|
||||
// Authenticate a user
|
||||
$user = User::factory()->create();
|
||||
Auth::login($user);
|
||||
|
||||
// Create import record
|
||||
$import = Import::create([
|
||||
'uuid' => $uuid,
|
||||
'user_id' => $user->id,
|
||||
'import_template_id' => null,
|
||||
'client_id' => null,
|
||||
'source_type' => 'csv',
|
||||
'file_name' => basename($path),
|
||||
'original_name' => 'test-import.csv',
|
||||
'disk' => $disk,
|
||||
'path' => $path,
|
||||
'size' => strlen($csv),
|
||||
'status' => 'uploaded',
|
||||
'meta' => ['has_header' => true],
|
||||
]);
|
||||
|
||||
// Test download endpoint
|
||||
$response = test()->get(route('imports.download', ['import' => $import->id]));
|
||||
|
||||
$response->assertSuccessful();
|
||||
expect($response->headers->get('Content-Disposition'))->toContain('test-import.csv');
|
||||
|
||||
// Clean up
|
||||
Storage::disk($disk)->delete($path);
|
||||
});
|
||||
|
||||
it('returns 404 when file does not exist', function () {
|
||||
// Authenticate a user
|
||||
$user = User::factory()->create();
|
||||
Auth::login($user);
|
||||
|
||||
// Create import record with non-existent file
|
||||
$import = Import::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'user_id' => $user->id,
|
||||
'import_template_id' => null,
|
||||
'client_id' => null,
|
||||
'source_type' => 'csv',
|
||||
'file_name' => 'missing.csv',
|
||||
'original_name' => 'missing.csv',
|
||||
'disk' => 'local',
|
||||
'path' => 'imports/nonexistent.csv',
|
||||
'size' => 0,
|
||||
'status' => 'uploaded',
|
||||
'meta' => ['has_header' => true],
|
||||
]);
|
||||
|
||||
// Test download endpoint
|
||||
$response = test()->get(route('imports.download', ['import' => $import->id]));
|
||||
|
||||
$response->assertNotFound();
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user