Feedback-Umsetzung (dev/2026-07-22/feedback-analyse-2026-07-24.md, alle 10 Punkte):
- VIP-Statistik: eigener Berater ('ich', Linie 0) in Neue-Kundenabos- und beiden Top-10-Listen; Top-10-Umsatz sortiert nach abgerechneten Ist-Punkten + Abo-Anzahl-Spalte; Fußnote nicht-payline-wirksame Punkte (SalesVolumePoints::nonPaylinePoints)
- Führungskräfte-Liste: beide Sichten 'direkt' (an nächster FK abgeschnitten, additiv) und 'gesamt' (komplette Downline), Gesamt-Spalte nach Kundenzählweise
- Team-Abos: je Ebene 'abgerechnet (Monat)' und 'bis zum 25. erwartet'; Payline-Karte mit Teamabo-/Kundenabo-Zählern
- Incentive-Live-Ranking: Qualifizierte zuerst nummeriert (fixt auch isWinner rank<=max_winners)
- Porto: Netto-/Brutto-Kennzeichnung (Berater netto, Endkunden inkl. MwSt., portal_view-Flag; auch CRM-/Shop-Warenkorb + Checkout), Yard::shipping_tax-Fix
- Struktur-Ansicht: Abo-Badges 'A' (eigenes Abo) und '(n)' (Kundenabos) je Teampartner, gebatcht
- Abo-Löschung: Softdelete setzt active=0 (UserAbo deleting-Hook) + Bereinigungs-Migration für gelöschte-aber-aktive Abos
- Doku: technische Analyse + Kundinnen-Feedback-Dokument unter dev/2026-07-22/
- Tests: IncentiveRankingTest, TeamStructureAboBadgesTest, YardShippingTaxTest (neu); BackofficeStatisticsListsTest, TeamAboOverviewTest, PaylineForecastServiceTest, AboAdminDeleteTest, AboOneTimeViewTest erweitert
Außerdem enthalten (Branch-WIP vor dem Feedback): DATEV-Abgleich-Fixes 08+09/2025, USt-ID-Live-Validierung sowie restliche unkommittete Stände (u. a. Abo-Pause-Sprachkeys).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
259 lines
9.2 KiB
PHP
259 lines
9.2 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use App\Models\DcFile;
|
||
use App\Models\File;
|
||
use App\Models\ShoppingOrder;
|
||
use App\Models\UserCredit;
|
||
use App\Models\UserInvoice;
|
||
use App\Repositories\CreditRepository;
|
||
use Auth;
|
||
use Response;
|
||
use Storage;
|
||
|
||
class FileController extends Controller
|
||
{
|
||
/**
|
||
* Create a new controller instance.
|
||
*
|
||
* @return void
|
||
*/
|
||
public function __construct() {}
|
||
|
||
private function isPermissionShoppingOrder($shopping_order)
|
||
{
|
||
// Portal-Kunden (auth:customers) – Prüfung über shopping_user (billing_email + member_id)
|
||
if (Auth::guard('customers')->check()) {
|
||
$customer = Auth::guard('customers')->user();
|
||
if ($customer->shopping_user_id) {
|
||
$member = $customer->shoppingUser;
|
||
if ($member && $shopping_order->shopping_user) {
|
||
$orderUser = $shopping_order->shopping_user;
|
||
if (
|
||
$orderUser->billing_email === $member->billing_email
|
||
&& $orderUser->member_id === $member->member_id
|
||
) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Admin / Berater (auth:user)
|
||
if (Auth::check()) {
|
||
$user_id = $shopping_order->auth_user_id ?: $shopping_order->member_id;
|
||
if (Auth::user()->isAdmin() || $user_id == Auth::user()->id) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
abort(404);
|
||
}
|
||
|
||
private function isPermissionUserCredit($user_credit)
|
||
{
|
||
if (Auth::user()->isAdmin() || $user_credit->user_id == Auth::user()->id) {
|
||
return true;
|
||
}
|
||
abort(404);
|
||
}
|
||
|
||
private function isPermissionAuth()
|
||
{
|
||
if (Auth::check()) {
|
||
return true;
|
||
}
|
||
abort(403, 'Nicht autorisiert');
|
||
}
|
||
|
||
public function show($id = null, $from = null, $do = 'file', $locale = null)
|
||
{
|
||
|
||
$path = '';
|
||
$filename = '';
|
||
$disk = 'public';
|
||
/*if($disk === 'user'){
|
||
$file = \App\Models\File::findOrFail($id);
|
||
$this->isPermission($file->user_id);
|
||
$path = Storage::disk($disk)->path($file->dir.$file->filename);
|
||
if (file_exists($path)) {
|
||
return Response::file($path);
|
||
}
|
||
}*/
|
||
if ($from === 'invoice') {
|
||
$shopping_order = ShoppingOrder::findOrFail($id);
|
||
if ($shopping_order->user_invoice) {
|
||
$this->isPermissionShoppingOrder($shopping_order);
|
||
$user_invoice = $shopping_order->user_invoice;
|
||
$disk = $user_invoice->disk;
|
||
// Lokalisierte Version wenn angegeben
|
||
if ($locale && $locale !== 'de') {
|
||
$filename = $user_invoice->getFilenameLocale($locale);
|
||
$path = $user_invoice->getDownloadPathLocale($locale);
|
||
} else {
|
||
$filename = $user_invoice->filename;
|
||
$path = $user_invoice->getDownloadPath();
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($from === 'delivery') {
|
||
$shopping_order = ShoppingOrder::findOrFail($id);
|
||
if ($shopping_order->user_invoice) {
|
||
$this->isPermissionShoppingOrder($shopping_order);
|
||
$user_invoice = $shopping_order->user_invoice;
|
||
$disk = $user_invoice->disk;
|
||
// Lokalisierte Version wenn angegeben
|
||
if ($locale && $locale !== 'de') {
|
||
$filename = $user_invoice->getFilenameLocale($locale);
|
||
// Für Lieferschein den lokalisierten Pfad ermitteln
|
||
$localizedDeliveryFilename = str_replace('.pdf', '-'.$locale.'.pdf', $user_invoice->delivery_filename);
|
||
$localizedPath = $user_invoice->delivery_dir.$localizedDeliveryFilename;
|
||
if (Storage::disk($disk)->exists($localizedPath)) {
|
||
$filename = $localizedDeliveryFilename;
|
||
$path = $localizedPath;
|
||
} else {
|
||
$filename = $user_invoice->delivery_filename;
|
||
$path = $user_invoice->getDownloadPathDelivery();
|
||
}
|
||
} else {
|
||
$filename = $user_invoice->delivery_filename;
|
||
$path = $user_invoice->getDownloadPathDelivery();
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($from === 'cancellation') {
|
||
$shopping_order = ShoppingOrder::findOrFail($id);
|
||
$this->isPermissionShoppingOrder($shopping_order);
|
||
|
||
// Stornorechnung finden: cancellation=true UND cancellation_id=null
|
||
// (Die Original-Rechnung hat auch cancellation=true, aber MIT cancellation_id)
|
||
$cancellation_invoice = UserInvoice::where('shopping_order_id', $shopping_order->id)
|
||
->where('cancellation', true)
|
||
->whereNull('cancellation_id')
|
||
->first();
|
||
|
||
if ($cancellation_invoice) {
|
||
$disk = $cancellation_invoice->disk;
|
||
// Lokalisierte Version wenn angegeben
|
||
if ($locale && $locale !== 'de') {
|
||
$filename = $cancellation_invoice->getFilenameLocale($locale);
|
||
$path = $cancellation_invoice->getDownloadPathLocale($locale);
|
||
} else {
|
||
$filename = $cancellation_invoice->filename;
|
||
$path = $cancellation_invoice->getDownloadPath();
|
||
}
|
||
} else {
|
||
return Response::make('Stornorechnung nicht gefunden.', 404);
|
||
}
|
||
}
|
||
|
||
if ($from === 'credit') {
|
||
$user_credit = UserCredit::findOrFail($id);
|
||
$this->isPermissionUserCredit($user_credit);
|
||
$disk = $user_credit->disk;
|
||
// Lokalisierte Version wenn angegeben
|
||
if ($locale && $locale !== 'de') {
|
||
$filename = $user_credit->getFilenameLocale($locale);
|
||
$path = $user_credit->getDownloadPathLocale($locale);
|
||
} else {
|
||
$filename = $user_credit->filename;
|
||
$path = $user_credit->getDownloadPath();
|
||
}
|
||
}
|
||
|
||
if ($from === 'credit_detail') {
|
||
$user_credit = UserCredit::findOrFail($id);
|
||
$this->isPermissionUserCredit($user_credit);
|
||
|
||
return $this->create_credit_detail($user_credit, $do);
|
||
|
||
/*
|
||
$filename = $user_credit->filename;
|
||
$disk = $user_credit->disk;
|
||
$path = $user_credit->getDownloadPath();
|
||
*/
|
||
}
|
||
|
||
if ($from === 'dc_file') {
|
||
// $this->isPermissionAuth();
|
||
$dc_file = DcFile::findOrFail($id);
|
||
$filename = $dc_file->filename;
|
||
$disk = 'public';
|
||
$path = $dc_file->getFile();
|
||
}
|
||
if ($from === 'dc_thumb') {
|
||
// $this->isPermissionAuth();
|
||
$dc_file = DcFile::findOrFail($id);
|
||
$filename = $dc_file->filename;
|
||
$disk = 'public';
|
||
$path = $dc_file->getThumb();
|
||
}
|
||
|
||
if ($from === 'dc_big') {
|
||
// $this->isPermissionAuth();
|
||
$dc_file = DcFile::findOrFail($id);
|
||
$filename = $dc_file->filename;
|
||
$disk = 'public';
|
||
$path = $dc_file->getBig();
|
||
}
|
||
|
||
if ($from === 'user') {
|
||
$file = File::findOrFail($id);
|
||
$filename = $file->filename;
|
||
$disk = 'user';
|
||
$path = $file->dir.$file->filename;
|
||
}
|
||
|
||
if (! Storage::disk($disk)->exists($path)) {
|
||
return Response::make('Datei nicht gefunden.', 404);
|
||
}
|
||
|
||
if ($do === 'download') {
|
||
return Storage::disk($disk)->download($path, $filename);
|
||
}
|
||
|
||
$file = Storage::disk($disk)->get($path);
|
||
$mime = Storage::disk($disk)->mimeType($path);
|
||
if (isset($file)) {
|
||
if ($do === 'stream') {
|
||
return Storage::disk($disk)->response($path, $filename);
|
||
}
|
||
|
||
if ($do === 'file') {
|
||
return Response::make($file, 200)
|
||
->header('Content-Type', $mime)
|
||
->header('Content-Length', strlen($file))
|
||
->header('Content-disposition', 'filename="'.$filename.'"');
|
||
}
|
||
if ($do === 'image') {
|
||
return Response::make($file, 200)
|
||
->header('Content-Type', $mime);
|
||
}
|
||
if ($do === 'pdf') {
|
||
$path = storage_path().'/app/public/'.$path;
|
||
|
||
$headers = [
|
||
'Content-Type:'.$mime,
|
||
// 'Content-Length: ' . $file->size
|
||
// 'Content-Disposition: ' . $stream . '; filename=' . $file->original_name
|
||
];
|
||
|
||
return Response::download($path, $filename, $headers);
|
||
}
|
||
}
|
||
}
|
||
|
||
private function create_credit_detail(UserCredit $user_credit, $do)
|
||
{
|
||
abort_if($user_credit->user === null, 404, 'User zur Gutschrift nicht gefunden.');
|
||
|
||
$credit_repo = new CreditRepository($user_credit->user);
|
||
|
||
return $credit_repo->create_report($user_credit, $do);
|
||
// \Session()->flash('alert-success', "Gutschrift erstellt");
|
||
|
||
}
|
||
}
|