commit 08-2025

This commit is contained in:
Kevin Adametz 2025-08-12 15:51:04 +02:00
parent 9b54eb0512
commit 02f2a4c23e
184 changed files with 31653 additions and 22327 deletions

View file

@ -0,0 +1,252 @@
<?php
namespace App\Console\Commands;
use App\Models\PaymentReminder;
use App\Models\ShoppingPayment;
use App\Services\PaymentReminderService;
use Carbon\Carbon;
use Illuminate\Console\Command;
/**
* Command für automatische Zahlungserinnerungen
*
* Dieser Command wird als Cron-Job ausgeführt und sendet automatisch
* Zahlungserinnerungen basierend auf den konfigurierten Intervallen.
*
* Verwendung:
* php artisan payments:reminders
*
* Cron-Job Konfiguration (täglich um 9:00 Uhr):
* 0 9 * * * cd /path/to/project && php artisan payments:reminders >> /dev/null 2>&1
*
* Oder für stündliche Ausführung:
* 0 * * * * cd /path/to/project && php artisan payments:reminders >> /dev/null 2>&1
*
* Logs werden automatisch in storage/logs/laravel.log geschrieben
*/
class PaymentsReminders extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'payments:reminders';
protected $description = 'Run Payments Reminders';
private $timeStart;
private $dev = false;
private $paymentReminderService;
private $stats = [
'total_processed' => 0,
'reminders_sent' => 0,
'errors' => 0,
'skipped' => 0
];
public function __construct(PaymentReminderService $paymentReminderService)
{
parent::__construct();
$this->paymentReminderService = $paymentReminderService;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
\Log::info('Starting PaymentsReminders Command', ['timestamp' => now()]);
$this->info('RUN Command Payments Reminders: '.date('d.m.Y H:i'));
$this->timeStart = microtime(true);
try {
$this->functionReminder();
$executionTime = round(microtime(true) - $this->timeStart, 2);
$this->info("\n=== PAYMENT REMINDERS ABGESCHLOSSEN ===");
$this->info("Ausführungszeit: {$executionTime} Sekunden");
$this->info("Statistiken:");
$this->info(" - Gesamt verarbeitet: {$this->stats['total_processed']}");
$this->info(" - Erinnerungen gesendet: {$this->stats['reminders_sent']}");
$this->info(" - Fehler: {$this->stats['errors']}");
$this->info(" - Übersprungen: {$this->stats['skipped']}");
\Log::info('PaymentsReminders Command completed successfully', [
'execution_time' => $executionTime,
'stats' => $this->stats
]);
return 0;
} catch (\Exception $e) {
\Log::error('PaymentsReminders Command failed', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$this->error('Command failed: ' . $e->getMessage());
return 1;
}
}
/**
* Hauptfunktion für die Verarbeitung der Zahlungserinnerungen
*/
private function functionReminder()
{
$this->info('=== STARTE PAYMENT REMINDERS ===');
// Hole alle aktiven PaymentReminder und gruppiere sie nach clearingtype
$payment_reminders = PaymentReminder::where('active', true)->get();
$this->info("Gefundene aktive PaymentReminder: " . $payment_reminders->count());
if ($payment_reminders->isEmpty()) {
$this->warn("Keine aktiven PaymentReminder gefunden!");
return;
}
// Finde für jeden clearingtype das kleinste Intervall (in Tagen)
$intervals = $this->paymentReminderService->getActiveIntervals();
$this->info("Gefundene clearingtypes mit kleinsten Intervallen:");
foreach($intervals as $clearingtype => $interval){
$this->line(" - {$clearingtype}: {$interval} Tage");
}
// Verarbeite jeden clearingtype mit seinem kleinsten Intervall
foreach($intervals as $clearingtype => $interval){
$this->info("\n--- Verarbeite clearingtype: {$clearingtype} mit Intervall: {$interval} Tage ---");
$date = Carbon::now()->subDays($interval);
$this->line("Suche Zahlungen vor: " . $date->format('d.m.Y H:i:s'));
// Hole nur die neueste ShoppingPayment pro shopping_order_id
$shopping_payments = $this->paymentReminderService->getOpenPaymentsForClearingType($clearingtype, $interval);
$this->info("Gefundene offene Zahlungen für {$clearingtype}: " . $shopping_payments->count());
if ($shopping_payments->isEmpty()) {
$this->line(" Keine Zahlungen für {$clearingtype} gefunden.");
continue;
}
// Verarbeite jede Zahlung
foreach($shopping_payments as $shopping_payment){
$this->processPayment($shopping_payment, $clearingtype);
}
}
}
/**
* Verarbeitet eine einzelne Zahlung und sendet ggf. eine Erinnerung
*/
private function processPayment($shopping_payment, $clearingtype)
{
$this->stats['total_processed']++;
try {
$this->line(" Verarbeite Order ID: {$shopping_payment->shopping_order_id}, Created: {$shopping_payment->created_at->format('d.m.Y H:i:s')}, Amount: {$shopping_payment->amount}, Reminder: {$shopping_payment->reminder}");
// Prüfe ob eine Erinnerung gesendet werden soll
if ($this->shouldSendReminder($shopping_payment, $clearingtype)) {
$this->sendReminderForPayment($shopping_payment);
} else {
$this->line(" ⏭️ Übersprungen - Keine Erinnerung fällig");
$this->stats['skipped']++;
}
} catch (\Exception $e) {
$this->error(" ❌ Fehler bei Order ID {$shopping_payment->shopping_order_id}: " . $e->getMessage());
$this->stats['errors']++;
\Log::error('Error processing payment reminder', [
'order_id' => $shopping_payment->shopping_order_id,
'payment_id' => $shopping_payment->id,
'error' => $e->getMessage()
]);
}
}
/**
* Prüft ob eine Erinnerung für diese Zahlung gesendet werden soll
*
* Logik:
* - Erste Erinnerung: Nach X Tagen ab Bestelldatum
* - Weitere Erinnerungen: Nach Y Tagen ab letzter Erinnerung
*/
private function shouldSendReminder($shopping_payment, $clearingtype)
{
// Hole alle aktiven Erinnerungen für diesen Clearingtype
$payment_reminders = PaymentReminder::where('active', true)
->where('clearingtype', $clearingtype)
->orderBy('interval', 'asc')
->get();
if ($payment_reminders->isEmpty()) {
return false;
}
// Wenn alle Erinnerungen bereits gesendet wurden
if ($shopping_payment->reminder >= $payment_reminders->count()) {
return false;
}
// Hole die nächste Erinnerung
$next_reminder = $payment_reminders[$shopping_payment->reminder];
// Wenn noch keine Erinnerung gesendet wurde, prüfe das erste Intervall
if ($shopping_payment->reminder == 0) {
$daysSinceOrder = $shopping_payment->created_at->diffInDays(now());
return $daysSinceOrder >= $next_reminder->interval;
}
// Wenn bereits Erinnerungen gesendet wurden, prüfe das nächste Intervall
if ($shopping_payment->reminder_date) {
$current_reminder = $payment_reminders[$shopping_payment->reminder - 1];
$interval_difference = $next_reminder->interval - $current_reminder->interval;
$next_reminder_date = Carbon::parse($shopping_payment->reminder_date)->addDays($interval_difference);
return now()->gte($next_reminder_date);
}
return false;
}
/**
* Sendet eine Erinnerung für eine spezifische Zahlung
*/
private function sendReminderForPayment($shopping_payment)
{
try {
$this->line(" 📧 Sende Erinnerung...");
$result = $this->paymentReminderService->sendReminder($shopping_payment);
if ($result) {
$this->line(" ✅ Erinnerung erfolgreich gesendet");
$this->stats['reminders_sent']++;
// Log für Cron-Job
\Log::info('Payment reminder sent via cron', [
'order_id' => $shopping_payment->shopping_order_id,
'payment_id' => $shopping_payment->id,
'reminder_count' => $shopping_payment->reminder + 1,
'email' => $shopping_payment->shopping_order->shopping_user->billing_email ?? 'N/A'
]);
} else {
$this->line(" ⚠️ Keine Erinnerung gesendet (keine weitere Erinnerung verfügbar)");
$this->stats['skipped']++;
}
} catch (\Exception $e) {
$this->error(" ❌ Fehler beim Senden der Erinnerung: " . $e->getMessage());
$this->stats['errors']++;
\Log::error('Error sending payment reminder', [
'order_id' => $shopping_payment->shopping_order_id,
'payment_id' => $shopping_payment->id,
'error' => $e->getMessage()
]);
}
}
}

View file

@ -24,13 +24,22 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('payments:accounts')
/*$schedule->command('payments:accounts')
->sendOutputTo(storage_path('logs/cron.log'))
->appendOutputTo(storage_path('logs/cron-history.log'))
->emailOutputOnFailure(config('app.exception_mail'))
->onFailure(function () {
\Log::error('Payments:accounts command failed');
});
*/
$schedule->command('payments:reminders')
->sendOutputTo(storage_path('logs/cron.log'))
->appendOutputTo(storage_path('logs/cron-reminders.log'))
->emailOutputOnFailure(config('app.exception_mail'))
->onFailure(function () {
\Log::error('Payments:reminders command failed');
});
}
/**

View file

@ -4,6 +4,9 @@ namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Illuminate\Support\Facades\Mail;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
class Handler extends ExceptionHandler
{
@ -36,6 +39,9 @@ class Handler extends ExceptionHandler
*/
public function report(Throwable $exception)
{
if ($this->shouldReport($exception)) {
$this->sendEmail($exception);
}
parent::report($exception);
}
@ -52,4 +58,35 @@ class Handler extends ExceptionHandler
{
return parent::render($request, $exception);
}
public function sendEmail(Throwable $exception)
{
try {
$e = FlattenException::create($exception);
$handler = new HtmlErrorRenderer(true); // boolean, true raises debug flag...
$css = $handler->getStylesheet();
$content = $handler->getBody($e);
//Mail::to(config('app.exception_mail'))->send(new MailContact($contact));
// Verwende normale Mail-Klasse statt Facade, um Probleme bei der Initialisierung zu vermeiden
$to = config('app.exception_mail');
$subject = 'gruene-seele Exception: ' . \Request::fullUrl();
if ($to) {
\Mail::send('emails.exception', compact('css', 'content'), function ($message) use ($to, $subject) {
$message
->to($to)
->subject($subject)
;
});
}
} catch (Throwable $ex) {
// Einfache Fehlerprotokollierung ohne Facade
file_put_contents(
storage_path('logs/laravel-' . date('Y-m-d') . '.log'),
'[' . date('Y-m-d H:i:s') . '] exception-handler-error: ' . $ex->getMessage() . "\n",
FILE_APPEND
);
}
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Excel;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithHeadings;
class UserTeamExport implements FromCollection, WithHeadings
{
protected $collection;
protected $headings;
use Exportable;
public function __construct($data,$header)
{
$this->collection = $data;
$this->headings = $header;
}
public function collection()
{
return collect($this->collection);
}
public function headings(): array
{
return [$this->headings];
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Excel;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithHeadings;
class XLSExport implements FromCollection, WithHeadings
{
protected $collection;
protected $headings;
use Exportable;
public function __construct($data,$header)
{
$this->collection = $data;
$this->headings = $header;
}
public function collection()
{
return collect($this->collection);
}
public function headings(): array
{
return [$this->headings];
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\PaymentReminderService;
use Illuminate\Http\Request;
class PaymentReminderController extends Controller
{
/* not used at the moment */
private $paymentReminderService;
public function __construct(PaymentReminderService $paymentReminderService)
{
$this->paymentReminderService = $paymentReminderService;
}
/**
* Zeige die Payment Reminders Übersicht
*/
public function index()
{
$detailedData = $this->paymentReminderService->getDetailedPaymentsData();
$summaryData = $this->paymentReminderService->getAllOpenPayments();
// Statistiken für die Übersicht
$totalPayments = collect($detailedData)->count();
$totalAmount = collect($detailedData)->sum('amount');
$clearingTypes = collect($detailedData)->groupBy('clearingtype')->map->count();
return view('admin.payment.reminder.index', compact(
'detailedData',
'summaryData',
'totalPayments',
'totalAmount',
'clearingTypes'
));
}
}

View file

@ -1,200 +0,0 @@
<?php
namespace App\Http\Controllers\Evo;
use Auth;
use Request;
use App\User;
use Carbon\Carbon;
use App\Services\HTMLHelper;
use App\Models\ShoppingOrder;
use App\Exports\UserTeamExport;
use App\Models\ShoppingOrderItem;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use App\Services\BusinessPlan\ExportBot;
use Illuminate\Database\Eloquent\Collection;
class SalesController extends Controller
{
public function __construct()
{
$this->middleware('admin');
}
public function index()
{
$this->setFilterVars();
$data = [
'filter_months' => HTMLHelper::getTransMonths(),
'filter_years' => HTMLHelper::getYearRange(2022),
];
return view('admin.evaluation.salesvolume', $data);
}
public function download(){
if(Request::get('action') === "export"){
$objects = $this->initSearch(false);
$columns = [];
$filename = "gs-absatzmengen-".session('product_sales_vol_filter_month').'_'.session('product_sales_vol_filter_year')."-export";
$headers = array(
'#',
'Produkt',
'Artikelnummer',
'Menge',
);
if($objects){
foreach ($objects as $key => $obj){
$columns[] = array(
'id' => $key,
'name' => $obj['name'],
'number' => $obj['number'],
'value' => $obj['value'],
);
}
}
return Excel::download(new UserTeamExport($columns, $headers), $filename.'.xls');
}
}
private function setFilterVars(){
if(!session('product_sales_vol_filter_month')){
session(['product_sales_vol_filter_month' => intval(date('m'))]);
}
if(!session('product_sales_vol_filter_year')){
session(['product_sales_vol_filter_year' => intval(date('Y'))]);
}
if(Request::get('product_sales_vol_filter_month')){
session(['product_sales_vol_filter_month' => Request::get('product_sales_vol_filter_month')]);
}
if(Request::get('product_sales_vol_filter_year')){
session(['product_sales_vol_filter_year' => Request::get('product_sales_vol_filter_year')]);
}
}
private function initSearch($returnColl = true)
{
$this->setFilterVars();
$date_start = Carbon::parse('01.'.session('product_sales_vol_filter_month').'.'.session('product_sales_vol_filter_year'))->format('Y-m-d H:i:s');
$date_end = Carbon::parse('01.'.session('product_sales_vol_filter_month').'.'.session('product_sales_vol_filter_year'))->endOfMonth()->format('Y-m-d H:i:s');
$ShoppingOrders = ShoppingOrder::where('paid', 1)->where('mode', 'live')->whereBetween('created_at', [$date_start, $date_end])->get();
$objects = [];
foreach($ShoppingOrders as $ShoppingOrder){
foreach($ShoppingOrder->shopping_order_items as $shopping_order_item){
if($shopping_order_item->product){
if(isset($objects[$shopping_order_item->product->id])){
$value = intval($objects[$shopping_order_item->product->id]['value'] + $shopping_order_item->qty);
$objects[$shopping_order_item->product->id]['value'] = $value;
}else{
$objects[$shopping_order_item->product->id] = [
'name' => $shopping_order_item->product->name,
'number' => $shopping_order_item->product->number,
'value' => $shopping_order_item->qty
];
}
}
}
}
if($returnColl){
$collection = collect();
foreach($objects as $key => $obj){
$collection->push([
'id' => $key,
'name' => $obj['name'],
'number' => $obj['number'],
'value' => $obj['value'],
]);
}
return $collection;
}
return $objects;
}
public function datatable(){
$collection = $this->initSearch(true);
$collect = collect([
['id' => 1, 'name' => 'John', 'number'=>92012, 'value'=>123],
['id' => 2, 'name' => 'Jane', 'number'=>92012, 'value'=>123],
['id' => 3, 'name' => 'James', 'number'=>92012, 'value'=>123],
]);
return \DataTables::of($collection)->toJson();
}
/*private function testCheckFunction(){
//$date_start = Carbon::parse('01.'.session('product_sales_vol_filter_month').'.'.session('product_sales_vol_filter_year'))->format('Y-m-d');
//$date_end = Carbon::parse('01.'.session('product_sales_vol_filter_month').'.'.session('product_sales_vol_filter_year'))->endOfMonth()->format('Y-m-d');
$date_start = Carbon::parse('01.01.2024')->format('Y-m-d H:i:s');
$date_end = Carbon::parse('01.01.2024')->endOfMonth()->format('Y-m-d H:i:s');
dump($date_start);
dump($date_end);
$ShoppingOrders = ShoppingOrder::where('mode', 'live')->whereBetween('created_at', [$date_start, $date_end])->get();
$objects = [];
$counter = 0;
foreach($ShoppingOrders as $ShoppingOrder){
foreach($ShoppingOrder->shopping_order_items as $shopping_order_item){
if($shopping_order_item->product){
if($shopping_order_item->product->id === 122){
//dump($shopping_order_item->qty);
//$counter += $shopping_order_item->qty;
if(isset($objects[$shopping_order_item->product->id])){
$value = intval($objects[$shopping_order_item->product->id]['value'] + $shopping_order_item->qty);
$objects[$shopping_order_item->product->id]['value'] = $value;
}else{
$objects[$shopping_order_item->product->id] = [
'name' => $shopping_order_item->product->name,
'number' => $shopping_order_item->product->number,
'value' => $shopping_order_item->qty
];
}
}
}
}
}
$ShoppingOrderItems = ShoppingOrderItem::whereProductId(122)->whereBetween('created_at', [$date_start, $date_end])->get();
$counter = 0;
foreach($ShoppingOrderItems as $ShoppingOrderItem){
$counter += $ShoppingOrderItem->qty;
dump($ShoppingOrderItem->id);
}
// dump($objects);
dump($counter);
dd("OKAY");
}*/
}

View file

@ -27,7 +27,7 @@ class ModalController extends Controller
if(Request::ajax()){
if($data['action'] === 'shopping-order-change-member'){
$value = ShoppingOrder::find($data['id']);
$route = route('admin_sales_customers_detail', [$value->id]);
$route = route('admin_sales_detail', [$value->id]);
$ret = view("admin.modal.member", compact('value', 'data', 'route'))->render();
}
if($data['action'] === 'shopping-user-change-member'){

View file

@ -62,7 +62,7 @@ class PaymentInvoiceController extends Controller
return \DataTables::eloquent($query)
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
return '<a href="' . route('admin_sales_customers_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
return '<a href="' . route('admin_sales_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
})
->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->getFormattedTotalShipping()."";

View file

@ -0,0 +1,147 @@
<?php
namespace App\Http\Controllers;
use Carbon;
use Request;
use App\Models\PaymentReminder;
use App\Models\ShoppingPayment;
use App\Services\PaymentReminderService;
class PaymentReminderController extends Controller
{
private $filter_user_status;
private $paymentReminderService;
public function __construct(PaymentReminderService $paymentReminderService)
{
$this->middleware('auth');
$this->paymentReminderService = $paymentReminderService;
}
public function index()
{
// Hole die detaillierten Daten für die Tabellen-Ansicht
$detailedData = $this->paymentReminderService->getDetailedPaymentsData();
// $summaryData = $this->paymentReminderService->getAllOpenPayments();
// Statistiken für die Übersicht
$totalPayments = collect($detailedData)->count();
$totalAmount = collect($detailedData)->sum('amount')/100;
$clearingTypes = collect($detailedData)->groupBy('clearingtype')->map->count();
$data = [
'reminders' => PaymentReminder::all(),
'detailedData' => $detailedData,
//'summaryData' => $summaryData,
'totalPayments' => $totalPayments,
'totalAmount' => $totalAmount,
'clearingTypes' => $clearingTypes,
];
return view('admin.payment.reminder.index', $data);
}
public function create()
{
$reminder = new PaymentReminder();
$reminder->active = true;
$data = [
'reminder' => $reminder,
];
return view('admin.payment.reminder.edit', $data);
}
public function edit($id)
{
$data = [
'reminder' => PaymentReminder::find($id),
];
return view('admin.payment.reminder.edit', $data);
}
public function store()
{
$data = Request::all();
$data['active'] = isset($data['active']) ? true : false;
$data['action'] = isset($data['action']) ? $data['action'] : NULL;
if ($data['id'] === 'new') {
PaymentReminder::create($data);
} else {
$reminder = PaymentReminder::find($data['id']);
$reminder->update($data);
}
return redirect()->route('admin_payments_reminder')->with('success', 'Erinnerung gespeichert');
}
public function action($action, $id)
{
$payment = ShoppingPayment::find($id);
if($action == 'send_reminder'){
$bool = $this->paymentReminderService->sendReminder($payment);
if($bool){
\Session()->flash('alert-success', "Zahlungserinnerung gesendet");
}else{
\Session()->flash('alert-error', "Keine Zahlungserinnerung gesendet");
}
}
if($action == 'no_payment'){
$this->paymentReminderService->setNoNPayment($payment);
\Session()->flash('alert-success', "Zahlung als nicht bezahlt markiert");
}
return redirect()->route('admin_payments_reminder');
}
public function delete($id)
{
$reminder = PaymentReminder::find($id);
$reminder->delete();
return redirect()->route('admin_payments_reminder');
}
public function logs()
{
// Hole die Log-Statistiken für verschiedene Zeiträume
$stats7Days = $this->paymentReminderService->getLogStatistics(7);
$stats30Days = $this->paymentReminderService->getLogStatistics(30);
$stats90Days = $this->paymentReminderService->getLogStatistics(90);
// Hole die neuesten Logs
$recentLogs = $this->paymentReminderService->getPaymentReminderLogs(50);
// Filter-Parameter
$orderId = Request::get('order_id');
$action = Request::get('action');
$startDate = Request::get('start_date');
$endDate = Request::get('end_date');
// Gefilterte Logs
$filteredLogs = null;
if ($orderId || $action || $startDate || $endDate) {
if ($startDate && $endDate) {
$filteredLogs = $this->paymentReminderService->getLogsForDateRange($startDate, $endDate);
} elseif ($orderId) {
$filteredLogs = $this->paymentReminderService->getLogsForPayment($orderId);
} elseif ($action) {
$filteredLogs = $this->paymentReminderService->getPaymentReminderLogs(100, null, $action);
}
}
$data = [
'stats7Days' => $stats7Days,
'stats30Days' => $stats30Days,
'stats90Days' => $stats90Days,
'recentLogs' => $recentLogs,
'filteredLogs' => $filteredLogs,
'orderId' => $orderId,
'action' => $action,
'startDate' => $startDate,
'endDate' => $endDate,
];
return view('admin.payment.reminder.logs', $data);
}
}

View file

@ -4,7 +4,6 @@ namespace App\Http\Controllers;
use Request;
use App\Models\Setting;
use App\Models\UserShop;
use App\Services\Payment;
use App\Models\ShoppingUser;
use App\Models\ShoppingOrder;
@ -13,6 +12,7 @@ use App\Models\ShoppingPayment;
use App\Models\PaymentTransaction;
use App\Services\CustomerPriority;
use App\Repositories\InvoiceRepository;
use App\Services\PaymentService;
class SalesController extends Controller
{
@ -21,7 +21,167 @@ class SalesController extends Controller
$this->middleware('admin');
}
public function users(){
public function index(){
if(Request::get('reset') === 'filter'){
set_user_attr('filter_txaction', null);
set_user_attr('filter_member_id', null);
set_user_attr('filter_art', null);
set_user_attr('filter_shipped', null);
return redirect(route('admin_sales'));
}
//set Filter!
$filter_members = ShoppingOrder::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get();
$data = [
'filter_members' => $filter_members,
];
return view('admin.sales.index', $data);
}
public function detail($id){
$ShoppingOrder = ShoppingOrder::find($id);
if($ShoppingOrder->shipped == 0){
$ShoppingOrder->shipped = 1;
$ShoppingOrder->save();
}
$data = [
'shopping_order' => $ShoppingOrder,
'isAdmin' => true,
'isView' => $ShoppingOrder->auth_user_id ? 'sales_user' : 'sales_customer',
];
return view('admin.sales.detail', $data);
}
public function detailStore($id){
$data = Request::all();
$change_member_error = false;
if($data['action']==='shopping-order-change-member'){
if(!isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')){
$change_member_error = "Das Passwort ist falsch.";
}else{
//change
$shopping_order = ShoppingOrder::findOrFail($data['id']);
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
\Session()->flash('alert-save', true);
return redirect(route('admin_sales_detail', [$shopping_order->id]));
}
}
if($data['action']==='shopping-user-is-like-member'){
if(!isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')){
\Session()->flash('alert-error', 'Das Passwort ist falsch.');
return redirect($data['back']);
}else{
if(!isset($data['is_like_shopping_user_id'])){
\Session()->flash('alert-error', 'Keine Änderung ausgewählt');
return redirect($data['back']);
}
$shopping_user = ShoppingUser::findOrFail($data['id']);
$set_like_shopping_user = ShoppingUser::findOrFail($data['is_like_shopping_user_id']);
$send_member_mail = isset($data['send_member_mail']) ? true : false;
$change_shopping_user = isset($data['change_shopping_user']) ? true : false;
//Mail send in setIsLike
CustomerPriority::setIsLike($shopping_user, $set_like_shopping_user, $send_member_mail, $change_shopping_user);
\Session()->flash('alert-save', true);
return redirect($data['back']);
}
}
$ShoppingOrder = ShoppingOrder::find($id);
$data = [
'change_member_error' => $change_member_error,
'shopping_order' => $ShoppingOrder,
'isAdmin' => true,
'isView' => $ShoppingOrder->auth_user_id ? 'sales_user' : 'sales_customer',
];
return view('admin.sales.detail', $data);
}
public function datatable(){
$query = ShoppingOrder::with('shopping_user', 'shopping_payments')->select('shopping_orders.*');
set_user_attr('filter_txaction', Request::get('filter_txaction'));
if(Request::get('filter_txaction') != ""){
if(Request::get('filter_txaction') === 'NULL'){
$query->where('txaction', '=', NULL);
}else{
$query->where('txaction', '=', Request::get('filter_txaction'));
}
}
set_user_attr('filter_member_id', Request::get('filter_member_id'));
if(Request::get('filter_member_id') != ""){
$query->where('member_id', '=', Request::get('filter_member_id'));
}
set_user_attr('filter_art', Request::get('filter_art'));
if(Request::get('filter_art') != ""){
if(Request::get('filter_art') === 'user_order'){
$query->where('shopping_orders.auth_user_id', '!=', NULL)->where('payment_for', '!=', 6);
}elseif(Request::get('filter_art') === 'customer_order'){
$query->where('shopping_orders.auth_user_id', NULL);
}elseif(Request::get('filter_art') === 'user_for_customer'){
$query->where('shopping_user_id', '!=', NULL)->where('payment_for', '=', 6);
}
// $query->where('payment_for', '=', Request::get('filter_art'));
}
set_user_attr('filter_shipped', Request::get('filter_shipped'));
if(Request::get('filter_shipped') != ""){
$query->where('shipped', '=', Request::get('filter_shipped'));
}
return \DataTables::eloquent($query)
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
return '<a href="' . route('admin_sales_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
})
->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->created_at->format("d.m.Y");
})
->addColumn('txaction', function (ShoppingOrder $ShoppingOrder) {
return Payment::getShoppingOrderBadge($ShoppingOrder);
})
->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->getFormattedTotalShipping()."";
})
->addColumn('payment', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->getLastShoppingPayment('getPaymentType');
})
->addColumn('shipped', function (ShoppingOrder $ShoppingOrder) {
return '<span class="badge badge-pill badge-'.$ShoppingOrder->getShippedColor().'">'.$ShoppingOrder->getShippedType().'</span>';
})
->addColumn('payment_for', function (ShoppingOrder $ShoppingOrder) {
return Payment::getPaymentForTypeBadge($ShoppingOrder);
})
->addColumn('reference', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->getLastShoppingPayment('reference');
})
->addColumn('member_id', function (ShoppingOrder $ShoppingOrder) {
if($ShoppingOrder->member_id) {
return $ShoppingOrder->member_id ? '<a href="' . route('admin_lead_edit', [$ShoppingOrder->member_id]) . '">' . $ShoppingOrder->member->getFullName() . '</a>' : '';
}
if($ShoppingOrder->shopping_user && $ShoppingOrder->shopping_user->is_like){
return '<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
data-id="'.$ShoppingOrder->shopping_user->id.'"
data-action="shopping-user-is-like-member"
data-back="'.route('admin_sales').'"
data-modal="modal-xl"
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>';
}
return '';
})
->orderColumn('id', 'id $1')
->orderColumn('txaction', 'txaction $1')
->orderColumn('payment_for', 'payment_for $1')
->orderColumn('member_id', 'member_id $1')
->orderColumn('shipped', 'shipped $1')
->orderColumn('total_shipping', 'total_shipping $1')
->rawColumns(['id', 'member_id', 'txaction', 'user_shop_id', 'payment_for', 'shipped'])
->make(true);
}
/*public function users(){
if(Request::get('reset') === 'filter'){
return redirect(route('admin_sales_users'));
@ -105,7 +265,7 @@ class SalesController extends Controller
if(Request::get('reset') === 'filter'){
set_user_attr('filter_txaction', null);
set_user_attr('filter_member_id', null);
return redirect(route('admin_sales_customers'));
return redirect(route('admin_sales'));
}
$filter_members = ShoppingOrder::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get(); //->pluck('email', 'id')->unique()->toArray();
$data = [
@ -141,7 +301,7 @@ class SalesController extends Controller
$shopping_order = ShoppingOrder::findOrFail($data['id']);
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
\Session()->flash('alert-save', true);
return redirect(route('admin_sales_customers_detail', [$shopping_order->id]));
return redirect(route('admin_sales_detail', [$shopping_order->id]));
}
}
if($data['action']==='shopping-user-is-like-member'){
@ -169,7 +329,7 @@ class SalesController extends Controller
'isAdmin' => true,
'isView' => 'sales_customer',
];
return view('admin.sales.customer_detail', $data);
return view('admin.sales._detail', $data);
}
public function customersDatatable(){
@ -192,7 +352,7 @@ class SalesController extends Controller
return \DataTables::eloquent($query)
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
return '<a href="' . route('admin_sales_customers_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
return '<a href="' . route('admin_sales_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
})
->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) {
return $ShoppingOrder->created_at->format("d.m.Y");
@ -223,7 +383,7 @@ class SalesController extends Controller
return '<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
data-id="'.$ShoppingOrder->shopping_user->id.'"
data-action="shopping-user-is-like-member"
data-back="'.route('admin_sales_customers').'"
data-back="'.route('admin_sales').'"
data-modal="modal-xl"
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>';
}
@ -238,7 +398,7 @@ class SalesController extends Controller
->orderColumn('total_shipping', 'total_shipping $1')
->rawColumns(['id', 'member_id', 'txaction', 'user_shop_id', 'payment_for', 'shipped'])
->make(true);
}
}*/
public function store(){
$data = Request::all();
@ -306,67 +466,11 @@ class SalesController extends Controller
}
/* txaction ändern
änderung der txaction von der Bestellung, Status Zahlung, offen, bezahlt, keine zahlung */
if($data['action'] === 'store_txaction' && isset($data['txaction']) && isset($data['payment_id'])){
$shopping_order = ShoppingOrder::findOrFail($data['id']);
$shopping_payment = ShoppingPayment::findOrFail($data['payment_id']);
if($shopping_payment->txaction === $data['txaction']){
return back();
}
//shopping_order_margin Bestellung im partner Center
if($shopping_order->shopping_order_margin && $shopping_order->shopping_order_margin->from_payment_credit > 0){
$last_UserPayCredit = UserPayCredit::where('shopping_order_id', $shopping_order->id)->whereIn('status', [2, 4])->orderBy('id', 'DESC')->first();
//Status Keine Zahlung, Guthaben zurückführen, wenn status 2 / deduction from payment
if($last_UserPayCredit && $data['txaction'] === 'non' && $last_UserPayCredit->status === 2){
Payment::handelUserPayCredits($shopping_order, 'return');
}
//Status Zahlung, voher gab es eine Storno, Guthaben abziehen wenn status 4 / return from order
if($last_UserPayCredit && $last_UserPayCredit->status === 4 && ($data['txaction'] === 'open' || $data['txaction'] === 'paid')){
Payment::handelUserPayCredits($shopping_order, 'deduction');
}
}
$payt = PaymentTransaction::create([
'shopping_payment_id' => $shopping_payment->id,
'request' => 'transaction',
'txid' => 0,
'userid' => 0,
'status' => $shopping_payment->clearingtype,
'transmitted_data' => NULL,
'txaction' => $data['txaction'],
'mode' => $shopping_payment->mode,
]);
$shopping_order->txaction = $data['txaction'];
$shopping_order->paid = $payt->txaction === 'paid' ? true : false;
$shopping_order->save();
$shopping_payment->txaction = $data['txaction'];
$shopping_payment->save();
if($payt->status === 'vor' && $payt->txaction === 'paid'){
$send_link = Payment::paymentStatusPaidAction($shopping_order, true);
}
//handel credit loading by change when by $shopping_order_item->handl
if($shopping_order->shopping_user->is_for === 'cr'){
$last_UserPayCredit = UserPayCredit::where('shopping_order_id', $shopping_order->id)->whereIn('status', [7, 8])->orderBy('id', 'DESC')->first();
//Status Keine Zahlung, Guthaben abziehen, wenn status 7 <- wurde aufgeladen
if($data['txaction'] === 'non' && $last_UserPayCredit && $last_UserPayCredit->status === 7){
Payment::handelUserPayChargingCredits($shopping_order, 'remove');
}
//Status Zahlung, voher gab es eine Storno, Guthaben wieder aufladen, wenn bezahlt wenn status 8
if($last_UserPayCredit && $last_UserPayCredit->status === 8 && $data['txaction'] === 'paid'){
Payment::handelUserPayChargingCredits($shopping_order, 'add');
}
}
$edata = [
'mode' => $payt->mode,
'txaction' => $payt->txaction,
'send_link' => false,
];
//TODO can send MAIL
Payment::paymentStatusSendMail($shopping_order, $shopping_payment, $edata);
PaymentService::updateTransactionStatus($data['id'], $data['txaction'], $data['payment_id']);
}
}
@ -391,9 +495,21 @@ class SalesController extends Controller
}else{
$user_invoice = $invoice_repo->create($data);
}
return redirect(route('admin_sales_users_detail', [$shopping_order->id]));
return redirect(route('admin_sales_detail', [$shopping_order->id]));
}
}
}
public function sendLogisticMail($id){
$shopping_order = ShoppingOrder::findOrFail($id);
if(\App\Services\Invoice::isInvoice($shopping_order)){
\App\Services\Invoice::sendLogisticMail($shopping_order);
\Session()->flash('alert-success', "Rechnung / Lieferschein wurde an den Versand gesendet.");
}else{
\Session()->flash('alert-error', "Keine Rechnung vorhanden.");
}
return redirect(route('admin_sales_detail', [$shopping_order->id]));
}
}

View file

@ -43,7 +43,6 @@ class SalesController extends Controller
public function download()
{
$this->setFilterVars();
if (Request::get('action') === "filter") {

View file

@ -61,7 +61,7 @@ class PromotionController extends Controller
if(isset($data['action']) && $data['action'] === 'save-user-promotion'){
$rules = array(
'name' => 'required',
'user_promotion_url' => ' required|alpha_dash|profanity|'.'unique:promotion_users,url,'.$id.',id'.'|min:4|max:20|full_word_check',
'user_promotion_url' => ' required|alpha_dash|'.'unique:promotion_users,url,'.$id.',id'.'|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
@ -107,7 +107,7 @@ class PromotionController extends Controller
$unique .= ','.$data['puid'].',id';
}
$rules = array(
'user_promotion_url' => ' required|alpha_dash|profanity|'.$unique.'|min:4|max:20|full_word_check',
'user_promotion_url' => ' required|alpha_dash|'.$unique.'|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');

View file

@ -1,53 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\User;
use Request;
use Carbon;
use App\Models\ShoppingOrder;
class RevenueController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$start = 2021;
$end = date('Y');
$years = range($start, $end);
if(Request::get('filter_sales_year')){
$active_year = Request::get('filter_sales_year');
}else{
$active_year = $end;
}
$date1 = Carbon::parse('01.01.'.$active_year." 00:00:00")->format('Y-m-d H:i:s');
$date2 = Carbon::parse('31.12.'.$active_year." 23:59:59")->toDateString();
$values = ShoppingOrder::where('shopping_orders.auth_user_id', '!=', NULL) //::with('shopping_user', )->select('shopping_orders.*')
->where('mode', '=', 'live')
->where('paid', '=', 1)
->whereHas('shopping_order_items', function($q) {
$q->where('product_id', 34)->OrWhere('product_id', 35)->OrWhere('product_id', 36)->OrWhere('product_id', 67)->OrWhere('product_id', 69);
})
->whereBetween('created_at', [$date1, $date2])
->get();
$data = [
'years' => $years,
'active_year' => $active_year,
'values' => $values,
];
return view('user.revenue.index', $data);
}
}

View file

@ -54,7 +54,7 @@ class ShopController extends Controller
if(isset($data['action']) && $data['action'] === 'save-user-shop'){
$rules = array(
'name' => 'required',
'user_shop_url' => ' required|alpha_dash|profanity|'.'unique:user_shops,url,'.$user->shop->id.',id'.'|min:4|max:20|full_word_check',
'user_shop_url' => ' required|alpha_dash|'.'unique:user_shops,url,'.$user->shop->id.',id'.'|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
@ -84,7 +84,7 @@ class ShopController extends Controller
$unique .= ','.$data['usid'].',id';
}
$rules = array(
'user_shop_url' => ' required|alpha_dash|profanity|'.$unique.'|min:4|max:20|full_word_check',
'user_shop_url' => ' required|alpha_dash|'.$unique.'|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');

View file

@ -270,7 +270,7 @@ class UserShopController extends Controller
if(Request::get('shop_submit') == 'check'){
$rules = array(
'user_shop_name' => ' required|alpha_dash|profanity|unique:user_shops,name|min:4|max:20|full_word_check',
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if(in_array($value, config('profanity.full_word_check'))){
@ -291,7 +291,7 @@ class UserShopController extends Controller
if(Request::get('shop_submit') == 'action') {
$rules = array(
'user_shop_name' => ' required|alpha_dash|profanity|unique:user_shops,name|min:4|max:20|full_word_check',
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if(in_array($value, config('profanity.full_word_check'))){
@ -381,7 +381,7 @@ class UserShopController extends Controller
public function checkUserShopName(){
$rules = array(
'user_shop_name' => ' required|alpha_dash|profanity|unique:user_shops,name|min:4|max:20|full_word_check',
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
);
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if(in_array($value, config('profanity.full_word_check'))){

View file

@ -3,14 +3,15 @@
namespace App\Http\Controllers;
use App\Mail\MailActivateUser;
use App\User;
use Auth;
use Validator;
use Request;
use Carbon\Carbon;
use Illuminate\Database\Connection;
use App\Mail\MailActivateUser;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Request;
use Validator;
class UserUpdateEmailController extends Controller
{
@ -152,7 +153,7 @@ class UserUpdateEmailController extends Controller
protected function getToken()
{
return hash_hmac('sha256', str_random(40), config('app.key'));
return hash_hmac('sha256', Str::random(40), config('app.key'));
}
public function createActivation($user, array $data)

View file

@ -15,7 +15,7 @@ class Kernel extends HttpKernel
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,

View file

@ -2,15 +2,15 @@
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array|string
* @var array|string|null
*/
protected $proxies;
@ -19,5 +19,10 @@ class TrustProxies extends Middleware
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View file

@ -0,0 +1,188 @@
<?php
namespace App\Libraries;
//use FPDI in myMerge v2
//use FPDF;
//use FPDI;
class MyPDFMerger
{
private $_files; //['form.pdf'] ["1,2,4, 5-19"]
private $_fpdi;
public function __construct()
{
/* if(!class_exists("FPDF")) {
require_once(__DIR__.'/fpdf/fpdf.php');
}
if(!class_exists("FPDI")) {
require_once(__DIR__.'/fpdi/fpdi.php');
}*/
}
public function addPDF($filepath, $pages = 'all')
{
if (file_exists($filepath)) {
if (strtolower($pages) != 'all') {
$pages = $this->_rewritepages($pages);
}
$this->_files[] = array($filepath, $pages);
} else {
throw new \exception("Could not locate PDF on '$filepath'");
}
return $this;
}
public function myMerge($outputmode = 'browser', $outputpath = 'newfile.pdf', $theme = false)
{
if (!isset($this->_files) || !is_array($this->_files)): throw new \exception("No PDFs to merge."); endif;
$fpdi = new \setasign\Fpdi\Fpdi();
$first = 1;
//
//merger operations
foreach ($this->_files as $file) {
$filename = $file[0];
$filepages = $file[1];
$count = $fpdi->setSourceFile($filename);
//add the pages
if ($filepages == 'all') {
for ($i = 1; $i <= $count; $i++) {
$count = $fpdi->setSourceFile($filename);
$template = $fpdi->importPage($i);
$size = $fpdi->getTemplateSize($template);
$orientation = ($size['height'] > $size['width']) ? 'P' : 'L';
$fpdi->AddPage($orientation, array($size['width'], $size['height']));
if($theme){
$fpdi->setSourceFile(__DIR__ . '/../../public/pdf/'.$theme.'-'.$first.'.pdf');
if($first == 1){
$first = 2;
}
$backId = $fpdi->importPage(1);
$fpdi->useTemplate($backId);
}
$fpdi->useTemplate($template);
}
} else {
foreach ($filepages as $page) {
$count = $fpdi->setSourceFile($filename);
if (!$template = $fpdi->importPage($page)): throw new \exception("Could not load page '$page' in PDF '$filename'. Check that the page exists."); endif;
$size = $fpdi->getTemplateSize($template);
$orientation = ($size['h'] > $size['w']) ? 'P' : 'L';
$fpdi->AddPage($orientation, array($size['w'], $size['h']));
if($theme){
$fpdi->setSourceFile(__DIR__ . '/../../public/pdf/'.$theme.'-'.$first.'.pdf');
if($first == 1){
$first = 2;
}
$backId = $fpdi->importPage(1);
$fpdi->useTemplate($backId);
}
$fpdi->useTemplate($template);
}
}
//after first file (invoice) on bpaper
$slug = false;
}
//output operations
$mode = $this->_switchmode($outputmode);
if ($mode == 'S') {
return $fpdi->Output($outputpath, 'S');
} else {
if ($fpdi->Output($outputpath, $mode) == '') {
return true;
} else {
throw new \exception("Error outputting PDF to '$outputmode'.");
return false;
}
}
}
/**
* FPDI uses single characters for specifying the output location. Change our more descriptive string into proper format.
* @param $mode
* @return Character
*/
private function _switchmode($mode)
{
switch (strtolower($mode)) {
case 'download':
return 'D';
break;
case 'browser':
return 'I';
break;
case 'file':
return 'F';
break;
case 'string':
return 'S';
break;
default:
return 'I';
break;
}
}
/**
* Takes our provided pages in the form of 1,3,4,16-50 and creates an array of all pages
* @param $pages
* @return array
* @throws exception
*/
private function _rewritepages($pages)
{
$pages = str_replace(' ', '', $pages);
$part = explode(',', $pages);
//parse hyphens
foreach ($part as $i) {
$ind = explode('-', $i);
if (count($ind) == 2) {
$x = $ind[0]; //start page
$y = $ind[1]; //end page
if ($x > $y): throw new \exception("Starting page, '$x' is greater than ending page '$y'.");
return false; endif;
//add middle pages
while ($x <= $y): $newpages[] = (int)$x;
$x++; endwhile;
} else {
$newpages[] = (int)$ind[0];
}
}
return $newpages;
}
}
/*
$pdf = new PDFMerger;
$pdf->addPDF('samplepdfs/one.pdf', '1, 3, 4')
->addPDF('samplepdfs/two.pdf', '1-2')
->addPDF('samplepdfs/three.pdf', 'all')
->merge('file', 'samplepdfs/TEST2.pdf');
//REPLACE 'file' WITH 'browser', 'download', 'string', or 'file' for output options
//You do not need to give a file path for browser, string, or download - just the name.
*/

87
app/Mail/MailLogistic.php Normal file
View file

@ -0,0 +1,87 @@
<?php
namespace App\Mail;
use App\User;
use App\Services\Invoice;
use App\Models\ShoppingOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Storage;
use Illuminate\Contracts\Queue\ShouldQueue;
class MailLogistic extends Mailable
{
use Queueable, SerializesModels;
protected $shopping_order;
public $subject;
public function __construct(ShoppingOrder $shopping_order)
{
$this->shopping_order = $shopping_order;
$name = $shopping_order->shopping_user->billing_firstname . ' ' . $shopping_order->shopping_user->billing_lastname;
$company = $shopping_order->shopping_user->billing_company ?? '';
$this->subject = 'Partner';
if($shopping_order->user_white_label){
//Bei allen, die ein eigenes Logo haben
$this->subject .= ' (mit Logo)';
}else{
//Bei allen, die kein Tattoostudio sind
$this->subject = ' - ';
}
if($shopping_order->shopping_user->same_as_billing){
//Rechnungsadresse und Lieferadresse sind gleich
$this->subject = '';
}else{
//hat eine andere Lieferadresse
$this->subject = ' Lieferadresse';
}
$this->subject .= ' '.$company.' (' . $name . ')';
}
public function build()
{
$title = false;
$copy1line = false;
$filename = Invoice::getFilename($this->shopping_order);
$path = Invoice::getDownloadPath($this->shopping_order);
if (!Storage::disk('public')->exists($path)) {
return;
}
$file = Storage::disk('public')->path($path);
$mime = Storage::disk('public')->mimeType($path);
$mail = $this->view('emails.logistic')->with([
'title' => $title,
'copy1line' => $copy1line,
])->attach($file,[
'as' => $filename,
'mime' => $mime,
]);
//Wenn das Logo gesetzt ist und die Rechnungsadresse und Lieferadresse unterschiedlich sind, dann wird der Lieferschein angehängt
if($this->shopping_order->user_white_label && !$this->shopping_order->shopping_user->same_as_billing){
$filenameDelivery = Invoice::getDeliveryFilename($this->shopping_order);
$pathDelivery = Invoice::getDownloadPathDelivery($this->shopping_order);
if (!Storage::disk('public')->exists($pathDelivery)) {
return;
}
$fileDelivery = Storage::disk('public')->path($pathDelivery);
$mimeDelivery = Storage::disk('public')->mimeType($pathDelivery);
$mail->attach($fileDelivery,[
'as' => $filenameDelivery,
'mime' => $mimeDelivery,
]); // attach file;
}
return $mail;
}
}

59
app/Mail/MailLogitic.php Normal file
View file

@ -0,0 +1,59 @@
<?php
namespace App\Mail;
use App\User;
use App\Services\Invoice;
use App\Models\ShoppingOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Storage;
use Illuminate\Contracts\Queue\ShouldQueue;
class MailLogistic extends Mailable
{
use Queueable, SerializesModels;
protected $shopping_order;
public $subject;
public function __construct(ShoppingOrder $shopping_order)
{
$this->shopping_order = $shopping_order;
if($shopping_order->user_white_label){
//Bei allen, die ein eigenes Logo haben
$this->subject = 'Partner (mit Logo) - Firma (Vorname Nachname)';
}else{
//Bei allen, die kein Tattoostudio sind
$this->subject = 'Partner - Firma (Vorname Nachname)';
}
}
public function build()
{
$title = false;
$copy1line = false;
$filename = Invoice::getFilename($this->shopping_order);
$path = Invoice::getDownloadPath($this->shopping_order);
if (!Storage::disk('public')->exists($path)) {
return;
}
$file = Storage::disk('public')->path($path);
$mime = Storage::disk('public')->mimeType($path);
return $this->view('emails.blank')->with([
'title' => $title,
'copy1line' => $copy1line,
])->attach($file,[
'as' => $filename,
'mime' => $mime,
]); // attach file;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Services\Util;
class PaymentReminderEmail extends Mailable
{
use Queueable, SerializesModels;
protected $emailSubject;
protected $message;
protected $order;
public $data;
/**
* Erstellt eine neue PaymentReminderEmail Instanz
*
* @param string $subject
* @param string $message
* @param object|null $user
* @param object|null $order
* @param float|null $paymentAmount
* @param string|null $dueDate
* @param string|null $paymentUrl
*/
public function __construct($subject, $message, $order = null)
{
$this->emailSubject = $subject;
$this->message = $message;
$this->order = $order;
}
/**
* Baut die E-Mail
*
* @return $this
*/
public function build()
{
$paymentUrl = route('user_myorder_detail', ['id' => $this->order->id]);
$buttonText = __('email.my_orders') ?: 'Meine Bestellungen';
return $this->subject($this->emailSubject)
->view('emails.payment_reminder')
->with([
'content' => $this->message,
'url' => $paymentUrl,
'button' => $buttonText,
]);
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
* Class PaymentReminder
*
* @property int $id
* @property string|null $title
* @property int|null $interval
* @property string|null $message
* @property string|null $action
* @property bool $active
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @package App\Models
*/
class PaymentReminder extends Model
{
protected $table = 'payment_reminders';
protected $casts = [
'interval' => 'int',
'active' => 'bool'
];
protected $fillable = [
'title',
'subject',
'interval',
'message',
'action',
'clearingtype',
'active'
];
protected static $clearingtypes = [
'fnc' => 'Rechnung',
'vor' => 'Vorkasse',
];
public function getClearingtype(){
return isset(self::$clearingtypes[$this->clearingtype]) ? self::$clearingtypes[$this->clearingtype] : 'Kein Typ';
}
public static function returnClearingtypes(){
return self::$clearingtypes;
}
}

View file

@ -105,6 +105,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value)
* @property array|null $delivery
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDelivery($value)
* @property bool $user_white_label
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrder whereUserWhiteLabel($value)
* @mixin \Eloquent
*/
class ShoppingOrder extends Model
@ -138,6 +140,7 @@ class ShoppingOrder extends Model
'paid',
'invoice',
'delivery',
'user_white_label',
'invoice_number',
'txaction',
'wp_invoice_path',
@ -146,7 +149,7 @@ class ShoppingOrder extends Model
'shipped',
'shipped_at',
'shipping_option',
'tracking'
'tracking',
];
protected $casts = [
@ -154,6 +157,7 @@ class ShoppingOrder extends Model
'invoice' => 'array',
'delivery' => 'array',
'shipped_at' => 'datetime',
'user_white_label' => 'boolean',
];
public static $shippedTypes = [
@ -161,6 +165,7 @@ class ShoppingOrder extends Model
1 => 'in Bearbeitung',
2 => 'versendet',
3 => 'abgeschlossen',
5 => 'Wartestellung',
4 => 'Abholung',
10 => 'storniert'
];
@ -213,6 +218,7 @@ class ShoppingOrder extends Model
2 => 'success',
3 => 'secondary',
4 => 'success',
5 => 'warning-dark',
10 => 'danger',
];

View file

@ -58,6 +58,14 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderMargin wherePartnerCommissionPendingTo($value)
* @property int|null $user_credit_id
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderMargin whereUserCreditId($value)
* @property bool $order_paid
* @property bool $out_paid
* @property \Illuminate\Support\Carbon|null $margin_pending_to
* @property bool|null $margin_paid
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrderMargin whereMarginPaid($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrderMargin whereMarginPendingTo($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrderMargin whereOrderPaid($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrderMargin whereOutPaid($value)
* @mixin \Eloquent
*/
class ShoppingOrderMargin extends Model
@ -113,7 +121,12 @@ class ShoppingOrderMargin extends Model
public static $statusTypes = [
0 => 'user order',
1 => '',
1 => 'Registrierung',
2 => 'Mitgliedschaft',
3 => 'Guthabenaufladung',
4 => 'VP.Bestellung Abholung',
5 => 'VP.Bestellung Lieferung',
6 => 'VP.Kundenbestellung',
7 => 'from promotion',
8 => 'from shop',
9 => 'storniert'

View file

@ -54,9 +54,18 @@ class ShoppingPayment extends Model
'reference',
'amount',
'currency',
'status',
'reminder',
'reminder_date',
'txaction',
'mode'
];
protected $casts = [
'reminder' => 'integer',
'reminder_date' => 'datetime',
];
public function shopping_order()
{
@ -91,6 +100,7 @@ class ShoppingPayment extends Model
if($this->clearingtype === 'non') {
return 'keine';
}
return 'keine';
}
public function getPaymentAmount(){

72
app/Policies/ModelPolicy.php Executable file
View file

@ -0,0 +1,72 @@
<?php
namespace App\Policies;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Database\Eloquent\Model;
abstract class ModelPolicy
{
use HandlesAuthorization;
abstract protected function getModelClass(): string;
public function viewAny(User $user)
{
return $user->can('view-any-' . $this->getModelClass());
}
public function view(User $user, Model $model)
{
if ($user->can('view-' . $this->getModelClass())) {
return true;
}
if ($user->can('view-self-' . $this->getModelClass())) {
return $this->isOwner($user, $model);
}
return false;
}
public function create(User $user)
{
return $user->can('create-' . $this->getModelClass());
}
public function update(User $user, Model $model)
{
if ($user->can('update-' . $this->getModelClass())) {
return true;
}
if ($user->can('update-self-' . $this->getModelClass())) {
return $this->isOwner($user, $model);
}
return false;
}
public function delete(User $user, Model $model)
{
if ($user->can('delete-' . $this->getModelClass())) {
return true;
}
if ($user->can('delete-self-' . $this->getModelClass())) {
return $this->isOwner($user, $model);
}
return false;
}
private function isOwner(User $user, Model $model): bool
{
if (!empty($user) && method_exists($model, 'user')) {
return $user->getKey() === $model->getRelation('user')->getKey();
}
return false;
}
}

View file

@ -2,6 +2,7 @@
namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -13,7 +14,7 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
//
Schema::defaultStringLength(191);
}
/**
@ -23,6 +24,10 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
//
if ($this->app->environment() !== 'production') {
$this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
}
// ...
}
}

View file

@ -6,7 +6,6 @@ use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;
class AuthServiceProvider extends ServiceProvider
{
/**
@ -15,7 +14,7 @@ class AuthServiceProvider extends ServiceProvider
* @var array
*/
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
@ -26,7 +25,12 @@ class AuthServiceProvider extends ServiceProvider
public function boot()
{
$this->registerPolicies();
Passport::routes();
// Die neuere Passport-Konfiguration verwendet separate Methoden
// anstelle von Passport::routes()
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
//
}

View file

@ -133,7 +133,7 @@ class ContractPDFRepository extends BaseRepository {
$filename = "Vertriebspartnervertrag.pdf";
Storage::disk($this->disk)->put($this->dir.$filename, $pdf->Output('S'));
$size = Storage::disk($this->disk)->size($this->dir.$filename);
$mine = Storage::disk($this->disk)->getMimeType($this->dir.$filename);
$mine = Storage::disk($this->disk)->mimeType($this->dir.$filename);
File::create([
'user_id' => $this->model->id,

View file

@ -43,7 +43,7 @@ class CreditRepository extends BaseRepository {
if(!Storage::disk('public')->exists( $dir )){
Storage::disk('public')->makeDirectory($dir); //creates directory
}
$path = Storage::disk('public')->getAdapter()->getPathPrefix();
$path = Storage::disk('public')->path('');
$filename = Credit::makeCreditFilename($credit_number);
$pdf->save($path.$dir.$filename);
@ -87,7 +87,7 @@ class CreditRepository extends BaseRepository {
private function finishUserCredit($user_credit){
//next number
Credit::makeNextCreditNumber();
//Partner Provision
//Partner Provision shopping order margin
$ShoppingOrderMargins = UserMarign::getPartnerCommissionItems($this->model->id, false);
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
$ShoppingOrderMargin->partner_commission_paid = true;
@ -96,7 +96,7 @@ class CreditRepository extends BaseRepository {
$ShoppingOrderMargin->save();
}
//Shop Provision
//Shop Provision shopping order margin
$ShoppingOrderMargins = UserMarign::getShopCommissionItems($this->model->id, false);
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
$ShoppingOrderMargin->margin_paid = true;
@ -105,7 +105,7 @@ class CreditRepository extends BaseRepository {
$ShoppingOrderMargin->save();
}
//Hinzugefügte Provision
//Hinzugefügte Provision user credit margin
$UserCreditMargins = UserMarign::getUserCreditMarginByUserID($this->model->id);
foreach($UserCreditMargins as $UserCreditMargin){
$UserCreditMargin->paid = true; //wurde ausgezahlt

View file

@ -22,6 +22,7 @@ class InvoiceRepository extends BaseRepository {
private $delivery_dir;
private $delivery_filename;
public function __construct(ShoppingOrder $model)
{
$this->model = $model;
@ -130,7 +131,7 @@ class InvoiceRepository extends BaseRepository {
if(!Storage::disk('public')->exists( $this->delivery_dir )){
Storage::disk('public')->makeDirectory($this->delivery_dir); //creates directory
}
$path = Storage::disk('public')->getAdapter()->getPathPrefix();
$path = Storage::disk('public')->path('');
$pdf_file = new InvoicePDF('pdf.invoice');
$pdf_file->create($data, $this->filename, 'save', $path.$this->dir);
@ -176,6 +177,10 @@ class InvoiceRepository extends BaseRepository {
foreach($whitelabel_image->attributes as $attribute){
if(in_array($attribute, $label->attributes)){
//found and overwrite
if(!$this->model->user_white_label){
$this->model->user_white_label = true;
$this->model->save();
}
$labels[$key] = $whitelabel_image;
}
}
@ -184,7 +189,6 @@ class InvoiceRepository extends BaseRepository {
}
}
}
foreach($labels as $key=>$label){
//label hat attribue
$varinats = [];

View file

@ -2,6 +2,7 @@
namespace App\Services;
use App\Mail\MailInvoice;
use App\Mail\MailLogistic;
use App\Services\Util;
use App\Models\Setting;
use App\Models\ShoppingOrder;
@ -118,4 +119,9 @@ class Invoice
}
Mail::to($billing_email)->bcc($bcc)->send(new MailInvoice($shopping_order));
}
public static function sendLogisticMail(ShoppingOrder $shopping_order){
$to = [config('app.logistic_mail')]; //['versand@aloe-vera.bio'];
Mail::to($to)->send(new MailLogistic($shopping_order));
}
}

View file

@ -51,7 +51,7 @@ class PDFMerger {
* Construct and initialize a new instance
* @param Filesystem $oFilesystem
*/
public function __construct(Filesystem $oFilesystem = null){
public function __construct($oFilesystem = null){
$this->oFilesystem = $oFilesystem;
$this->oFPDI = new FPDI();
$this->tmpFiles = collect([]);

View file

@ -4,7 +4,6 @@ namespace App\Services;
use App\User;
use App\Models\Product;
use App\Models\Setting;
use App\Mail\MailCheckout;
use App\Models\ProductBuy;
use App\Models\ShoppingOrder;
@ -19,15 +18,16 @@ class Payment
public static $txaction_text = [
'paid' => "bezahlt",
'appointed' => "offen",
'open' => "offen",
'appointed' => "offen (appointed)",
'failed' => "abbruch",
'extern' => "extern",
'open' => "offen",
'invoice_open' => "Re. offen",
'invoice_paid' => "Re. bezahlt",
'invoice_non' => "Re. keine Zahlung",
'non' => "keine Zahlung",
'non' => "keine Zahlung (non)",
'NULL' => 'keine Zahlung',
'prev' => "keine Zahlung (prev)",
];
public static $txaction_invoice = [
@ -56,10 +56,10 @@ class Payment
'invoice_open' => "warning",
'invoice_paid' => "success",
'invoice_non' => "danger",
'prev' => "warning",
];
public static function getFormattedTxaction($txaction){
if($txaction && isset(self::$txaction_text[$txaction])){
return self::$txaction_text[$txaction];
@ -360,26 +360,60 @@ class Payment
}
public static function paymentStatusSendMail(ShoppingOrder $shopping_order, $shopping_payment, $data){
$bcc = [];
$billing_email = $shopping_order->shopping_user->billing_email;
if(!$billing_email){
if($data['mode'] === 'test'){
$billing_email = config('app.checkout_test_mail');
}else{
$billing_email = config('app.checkout_mail');
}
public static function paymentStatusSendMail(ShoppingOrder $shopping_order, $shopping_payment, $data)
{
$billing_email = self::determineBillingEmail($shopping_order, $data);
$bcc = self::determineBccRecipients($shopping_order, $data);
try {
Mail::to($billing_email)
->bcc($bcc)
->send(new MailCheckout(
$data['txaction'],
$shopping_order,
$shopping_payment,
$data['send_link'],
$data['mode']
));
} catch (\Exception $e) {
\Log::error('Fehler beim E-Mail-Versand: ' . $e->getMessage());
}
if($data['mode'] === 'test'){
$bcc[] = config('app.checkout_test_mail');
}else{
$bcc[] = config('app.checkout_mail');
}
private static function determineBillingEmail($shopping_order, $data)
{
if (Util::isTestSystem()) {
return config('app.checkout_test_mail');
}
if(!$shopping_order->shopping_user->is_like && $shopping_order->shopping_user->member){
$billing_email = $shopping_order->shopping_user->billing_email;
if (!$billing_email) {
return $data['mode'] === 'test'
? config('app.checkout_test_mail')
: config('app.checkout_mail');
}
return $billing_email;
}
private static function determineBccRecipients($shopping_order, $data)
{
$bcc = [];
// Add checkout email to BCC
$bcc[] = $data['mode'] === 'test'
? config('app.checkout_test_mail')
: config('app.checkout_mail');
// Add member email to BCC if applicable
if ($data['mode'] !== 'test'
&& !Util::isTestSystem()
&& !$shopping_order->shopping_user->is_like
&& $shopping_order->shopping_user->member
) {
$bcc[] = $shopping_order->shopping_user->member->email;
}
Mail::to($billing_email)->bcc($bcc)->send(new MailCheckout($data['txaction'], $shopping_order, $shopping_payment, $data['send_link'], $data['mode']));
return $bcc;
}
}

View file

@ -1,269 +0,0 @@
<?php
namespace App\Services\Stats;
use Carbon\Carbon;
use App\Services\Util;
use App\Models\ShoppingOrder;
class Sales
{
private $month;
private $year;
private $products;
private $objects;
public function __construct()
{
$this->month = 0;
$this->year = 0;
$this->products = [];
$this->objects = [];
}
public function setFilterVars($month = null, $year = null, $products = null){
$this->month = $month ? $month : intval(date('m'));
$this->year = $year ? $year : intval(date('Y'));
$this->products = $products;
}
public function setFilterProducts(){
$ShoppingOrders = $this->getShoppingOrdersBy($this->month, $this->year);
$products = [];
foreach($ShoppingOrders as $ShoppingOrder){
foreach($ShoppingOrder->shopping_order_items as $shopping_order_item){
if($shopping_order_item->product && !$shopping_order_item->product->exclude_stats_sales && !isset($products[$shopping_order_item->product->id])){
$products[$shopping_order_item->product->id] = $shopping_order_item->product->name.' # '.
($shopping_order_item->product->single_commission ? $shopping_order_item->product->value_commission.' / '.$shopping_order_item->product->partner_commission : 'Staffelrabatt');
}
}
}
return $products;
}
private function getShoppingOrdersBy($month, $year){
if($month == '13'){ //all the year
$date_start = Carbon::parse('01.01.'.$year)->format('Y-m-d H:i:s');
$date_end = Carbon::parse('31.12.'.$year)->endOfMonth()->format('Y-m-d H:i:s');
}else{
$date_start = Carbon::parse('01.'.$month.'.'.$year)->format('Y-m-d H:i:s');
$date_end = Carbon::parse('01.'.$month.'.'.$year)->endOfMonth()->format('Y-m-d H:i:s');
}
return ShoppingOrder::where('paid', 1)->where('mode', 'live')->whereBetween('created_at', [$date_start, $date_end])->get();
}
public function getCollection(){
$this->getObjects();
$collection = collect();
foreach($this->objects as $key => $obj){
$collection->push([
'id' => $key,
'name' => $obj['name'],
'number' => $obj['number'],
'qty' => $obj['qty'],
'total' => $obj['total'],
'pre_qty' => $obj['pre_qty'],
'pre_total' => $obj['pre_total'],
'single_commission' => $obj['single_commission'],
'value_commission' => $obj['value_commission'],
'partner_commission' => $obj['partner_commission'],
]);
}
return $collection;
}
public function getObjects(){
$this->readObjects();
$this->readObjectsPreview();
return $this->objects;
}
private function readObjects()
{
$shoppingOrders = $this->getShoppingOrdersBy($this->month, $this->year);
$this->objects = [];
$subtotal_full = 0; // gesamtumsatz
$subtotal = 0; // gesamtumsatz ohne rabatte
$discount = 0; // gesamtrabatte
$subtotal_hide = 0; // ausgeschlossene Produkte
foreach($shoppingOrders as $ShoppingOrder){
$subtotal_full += $ShoppingOrder->subtotal_full;
$subtotal += $ShoppingOrder->subtotal;
$discount += $ShoppingOrder->discount;
foreach($ShoppingOrder->shopping_order_items as $shopping_order_item){
if($shopping_order_item->product){
if(!in_array($shopping_order_item->product->id, $this->products) && !$shopping_order_item->product->exclude_stats_sales){ //ausschließen der Produkte über filter und exclude_stats_sales
if(isset($this->objects[$shopping_order_item->product->id])){
$qty = intval($this->objects[$shopping_order_item->product->id]['qty'] + $shopping_order_item->qty);
$total = round($this->objects[$shopping_order_item->product->id]['total'] + ($shopping_order_item->price_net * $shopping_order_item->qty), 3);
$this->objects[$shopping_order_item->product->id]['qty'] = $qty;
$this->objects[$shopping_order_item->product->id]['total'] = $total;
}else{
$this->objects[$shopping_order_item->product->id] = [
'name' => $shopping_order_item->product->name,
'number' => $shopping_order_item->product->number,
'qty' => $shopping_order_item->qty,
'total' => round($shopping_order_item->price_net * $shopping_order_item->qty, 3),
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => $shopping_order_item->product->single_commission ? 'Ja' : 'Nein',
'value_commission' => $shopping_order_item->product->single_commission ? $shopping_order_item->product->value_commission : '',
'partner_commission' => $shopping_order_item->product->single_commission ? $shopping_order_item->product->partner_commission : '',
];
}
}else{
$subtotal_hide += $shopping_order_item->price_net * $shopping_order_item->qty;
}
}
}
}
$this->objects[9990] = [
'name' => 'Angezeigter Umsatz netto €',
'number' => '',
'qty' => '',
'total' => round($subtotal_full - $subtotal_hide, 2),
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => '',
'value_commission' => '',
'partner_commission' => '',
];
$this->objects[9991] = [
'name' => 'Ausgeblendeter Umsatz netto €',
'number' => '',
'qty' => '',
'total' => $subtotal_hide,
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => '',
'value_commission' => '',
'partner_commission' => '',
];
$this->objects[9992] = [
'name' => 'Gesamter Umsatz netto € (alle Verkäufe)',
'number' => '',
'qty' => '',
'total' => $subtotal_full,
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => '',
'value_commission' => '',
'partner_commission' => '',
];
$this->objects[9998] = [
'name' => 'Gesamte Rabatte netto € (alle Verkäufe)',
'number' => '',
'qty' => '',
'total' => ($discount),
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => '',
'value_commission' => '',
'partner_commission' => '',
];
$this->objects[9999] = [
'name' => 'Gesamt netto € (alle Verkäufe)',
'number' => '',
'qty' => '',
'total' => ($subtotal),
'pre_qty' => 0,
'pre_total' => 0,
'single_commission' => '',
'value_commission' => '',
'partner_commission' => '',
];
//format total
foreach($this->objects as $key => $obj){
$this->objects[$key]['total'] = formatNumber($obj['total']);
}
}
private function readObjectsPreview(){
$shoppingOrders = $this->getShoppingOrdersBy($this->month, $this->year-1);
$subtotal_full = 0; // gesamtumsatz
$subtotal = 0; // gesamtumsatz ohne rabatte
$discount = 0; // gesamtrabatte
$subtotal_hide = 0; // ausgeschlossene Produkte
foreach($shoppingOrders as $ShoppingOrder){
$subtotal_full += $ShoppingOrder->subtotal_full;
$subtotal += $ShoppingOrder->subtotal;
$discount += $ShoppingOrder->discount;
foreach($ShoppingOrder->shopping_order_items as $shopping_order_item){
if($shopping_order_item->product){
if(!in_array($shopping_order_item->product->id, $this->products) && !$shopping_order_item->product->exclude_stats_sales){ //ausschließen der Produkte über filter und exclude_stats_sales
if(isset($this->objects[$shopping_order_item->product->id])){ //einsetzen der Zahlen, wenn vorhanden
$qty = intval($this->objects[$shopping_order_item->product->id]['pre_qty'] + $shopping_order_item->qty);
$total = round($this->objects[$shopping_order_item->product->id]['pre_total'] + ($shopping_order_item->price_net * $shopping_order_item->qty), 3);
$this->objects[$shopping_order_item->product->id]['pre_qty'] = $qty;
$this->objects[$shopping_order_item->product->id]['pre_total'] = $total;
}else{ // nicht vorhanden, anlegen
$this->objects[$shopping_order_item->product->id] = [
'name' => $shopping_order_item->product->name,
'number' => $shopping_order_item->product->number,
'qty' => 0,
'total' => 0,
'pre_qty' => $shopping_order_item->qty,
'pre_total' => round($shopping_order_item->price_net * $shopping_order_item->qty, 3),
'single_commission' => $shopping_order_item->product->single_commission ? 'Ja' : 'Nein',
'value_commission' => $shopping_order_item->product->single_commission ? $shopping_order_item->product->value_commission : '',
'partner_commission' => $shopping_order_item->product->single_commission ? $shopping_order_item->product->partner_commission : '',
];
}
}else{
//ausgeschlossene Produkte
$subtotal_hide += $shopping_order_item->price_net * $shopping_order_item->qty;
}
}
}
}
$this->objects[9990]['pre_total'] = round($subtotal_full - $subtotal_hide, 2);
$this->objects[9991]['pre_total'] = $subtotal_hide;
$this->objects[9992]['pre_total'] = $subtotal_full;
$this->objects[9998]['pre_total'] = ($discount);
$this->objects[9999]['pre_total'] = ($subtotal);
//format total
foreach($this->objects as $key => $obj){
$this->objects[$key]['pre_total'] = formatNumber($obj['pre_total']);
}
}
}

View file

@ -30,6 +30,7 @@ class UserBot
//user die manuelle Gutschriften haben
$usersWithCreditMargin = $this->getUsersWithCreditMargin();
//user die Shop Provisionen haben
$usersWithShopCommission = $this->getUsersWithShopCommission(false);
@ -181,9 +182,9 @@ class UserBot
$entry->badge = \App\Services\Payment::getPaymentForTypeBadge($shoppingOrderMargin->shopping_order);
if ($shoppingOrderMargin->shopping_order->payment_for === 7 || $shoppingOrderMargin->shopping_order->payment_for === 8) {
$entry->link = route('admin_sales_customers_detail', [$shoppingOrderMargin->shopping_order->id]);
$entry->link = route('admin_sales_detail', [$shoppingOrderMargin->shopping_order->id]);
} else {
$entry->link = route('admin_sales_users_detail', [$shoppingOrderMargin->shopping_order->id]);
$entry->link = route('admin_sales_detail', [$shoppingOrderMargin->shopping_order->id]);
}
$entry->name = $shoppingOrderMargin->shopping_order->shopping_user->billing_firstname . " " .
@ -258,7 +259,8 @@ class UserBot
->whereOutPaid(false)
->whereCancellation(false)
->whereMarginPaid(false)
->whereNotNull('margin_pending_to');
->whereNotNull('margin_pending_to')
->whereIn('status', [7,8]);
if ($isPending) {
$query->where('margin_pending_to', '>=', Carbon::now());

View file

@ -0,0 +1,13 @@
<?php
namespace App\Services;
class PaymentHelper
{
public static $txaction_art = [
'user_order' => "Vertriebspartner",
'customer_order' => "Kundenbestellung",
'user_for_customer' => "VP.Kundenbestellung",
];
}

View file

@ -0,0 +1,453 @@
<?php
namespace App\Services;
use App\Models\Logger;
use App\Models\PaymentReminder;
use App\Models\ShoppingPayment;
use App\Mail\PaymentReminderEmail;
use App\Services\Util;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
class PaymentReminderService
{
protected $clearingtypes = [];
public function __construct()
{
$this->clearingtypes = PaymentReminder::returnClearingtypes();
}
/**
* Erstellt einen Log-Eintrag für Payment Reminder Aktivitäten
*/
private function createLog($action, $message, $model = null, $modelId = null, $level = 2)
{
return Logger::create([
'user_id' => null, // System-Aktion
'model_id' => $modelId,
'model' => $model,
'action' => $action,
'channel' => 'payment_reminder',
'message' => $message,
'level' => $level
]);
}
/**
* Hole alle aktiven Intervalle für Zahlungserinnerungen
*/
public function getActiveIntervals()
{
$intervals = [];
$payment_reminders = PaymentReminder::where('active', true)->get();
foreach($payment_reminders as $reminder) {
$intervals[$reminder->clearingtype] = $reminder->interval;
}
return $intervals;
}
/**
* Hole alle offenen Zahlungen für einen bestimmten clearingtype
*/
public function getOpenPaymentsForClearingType($clearingtype, $interval)
{
$date = Carbon::now()->subDays($interval);
$payments = ShoppingPayment::join('shopping_orders', 'shopping_payments.shopping_order_id', '=', 'shopping_orders.id')
->where('shopping_payments.clearingtype', '=', $clearingtype)
->where('shopping_payments.txaction', '=', 'open')
->where('shopping_payments.mode', '=', 'live')
->where('shopping_payments.created_at', '<', $date)
->where('shopping_payments.amount', '>', 0)
->whereNull('shopping_orders.deleted_at')
->whereIn('shopping_payments.id', function($query) use ($clearingtype, $date) {
$query->selectRaw('MAX(shopping_payments.id)')
->from('shopping_payments')
->join('shopping_orders', 'shopping_payments.shopping_order_id', '=', 'shopping_orders.id')
->where('shopping_payments.clearingtype', '=', $clearingtype)
->where('shopping_payments.txaction', '=', 'open')
->where('shopping_payments.mode', '=', 'live')
->where('shopping_payments.created_at', '<', $date)
->where('shopping_payments.amount', '>', 0)
->whereNull('shopping_orders.deleted_at')
->groupBy('shopping_payments.shopping_order_id');
})
->select('shopping_payments.*')
->get();
return $payments;
}
/**
* Hole alle offenen Zahlungen für alle clearingtypes
*/
public function getAllOpenPayments()
{
$intervals = $this->getActiveIntervals();
$results = [];
foreach($intervals as $clearingtype => $interval){
$date = Carbon::now()->subDays($interval);
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
$results[$clearingtype] = [
'interval' => $interval,
'date_limit' => $date,
'payments' => $payments,
'count' => $payments->count()
];
}
return $results;
}
/**
* Hole detaillierte Daten für Tabellen-Ansicht
*/
public function getDetailedPaymentsData()
{
$intervals = $this->getActiveIntervals();
$detailedData = [];
foreach($intervals as $clearingtype => $interval){
$date = Carbon::now()->subDays($interval);
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
foreach($payments as $payment){
$name = !isset($payment->shopping_order->shopping_user) ? 'Kein Name' : $payment->shopping_order->shopping_user->billing_firstname.' '.$payment->shopping_order->shopping_user->billing_lastname;
$email = !isset($payment->shopping_order->shopping_user) ? 'Keine Email' : $payment->shopping_order->shopping_user->billing_email;
$shipped = '<span class="badge badge-pill badge-'.$payment->shopping_order->getShippedColor().'">'.$payment->shopping_order->getShippedType().'</span>';
// Countdown für nächste Erinnerung berechnen
$countdown = $this->getNextReminderCountdown($payment);
$detailedData[] = [
'clearingtype' => $clearingtype,
'clearingtype_name' => $this->getClearingtype($clearingtype),
'interval_days' => $interval,
'date_limit' => $date->format('d.m.Y H:i:s'),
'order_id' => $payment->shopping_order_id,
'payment_id' => $payment->id,
'amount' => $payment->amount,
'created_at' => $payment->created_at->format('d.m.Y H:i:s'),
'days_old' => $payment->created_at->diffInDays(now()),
'payment' => $payment, // Vollständiges Payment-Objekt für weitere Verarbeitung
'name' => $name,
'email' => $email,
'shipped' => $shipped,
'reminder' => $payment->reminder,
'reminder_date' => $payment->reminder_date ? $payment->reminder_date->format('d.m.Y H:i:s') : null,
'countdown' => $countdown,
];
}
}
return $detailedData;
}
/**
* Sende die nächste Zahlungserinnerung
* noch kein reminder gesendet = 1. Zahlungserinnerung
* reminder > 0 die nächste zahlungserinnerung aus der liste holen
*/
public function sendReminder($payment)
{
//holen der nächsten zahlungserinnerung
$payment_reminder = $this->getReminder((int) $payment->reminder, $payment->clearingtype);
if(!$payment_reminder){
return false;
}
//zahlungserinnerung Platzhalter ersetzen.
$payment_reminder = $this->replacePlaceholder($payment, $payment_reminder);
//zahlungserinnerung senden
$emailSent = $this->sendReminderEmail($payment, $payment_reminder);
if ($emailSent) {
$this->createLog(
'email_sent',
"Zahlungserinnerung E-Mail gesendet an: {$payment->shopping_order->shopping_user->billing_email}, Subject: {$payment_reminder->subject}",
'ShoppingOrder',
$payment->shopping_order_id,
3
);
}
//action ausführen
if($payment_reminder->action === 'set_order_status_cancelled'){
$this->setNoNPayment($payment);
$payment->shopping_order->shipped = 10;
$payment->shopping_order->save();
$this->createLog(
'action_completed',
"Action abgeschlossen: Bestellung auf 'Storniert' gesetzt, Payment auf 'non' gesetzt",
'ShoppingOrder',
$payment->shopping_order_id,
3
);
}
//reminder setzen +1
$payment->reminder = (int) $payment->reminder + 1;
$payment->reminder_date = Carbon::now();
$payment->save();
$this->createLog(
'reminder_completed',
"Zahlungserinnerung für Payment ID: {$payment->id}, Order ID: {$payment->shopping_order_id}",
'ShoppingOrder',
$payment->shopping_order_id,
4
);
return true;
}
public function setNoNPayment($payment)
{
$this->createLog(
'set_non_payment',
"Setze Payment ID: {$payment->id} auf 'non' Status",
'ShoppingOrder',
$payment->shopping_order_id,
4
);
PaymentService::updateTransactionStatus($payment->shopping_order_id, 'non', $payment->id);
}
public function getClearingtype($clearingtype)
{
return isset($this->clearingtypes[$clearingtype]) ? $this->clearingtypes[$clearingtype] : $clearingtype;
}
public function getReminder($reminder, $clearingtype)
{
$payment_reminders = PaymentReminder::where('active', true)
->where('clearingtype', $clearingtype)
->orderBy('interval', 'asc')
->get();
if($payment_reminders->isEmpty()) {
return false;
}
// Wenn reminder größer ist als Anzahl der Erinnerungen
if($reminder >= $payment_reminders->count()) {
return false;
}
// Hole die Erinnerung an Position $reminder (0,1,2,3...)
return $payment_reminders[$reminder];
}
public function replacePlaceholder($payment, $payment_reminder)
{
$shopping_order = $payment->shopping_order;
$shopping_user = $shopping_order->shopping_user;
$replacements = [
'{billing_first_name}' => $shopping_user->billing_firstname,
'{billing_last_name}' => $shopping_user->billing_lastname,
'{order_number}' => '<b>'.$shopping_order->getLastShoppingPayment('reference').'</b>',
'{order_date}' => '<b>'.$shopping_order->created_at->format('d.m.Y').'</b>',
'{order_total}' => '<b>'.$shopping_order->getFormattedTotalShipping().'</b>'
];
$payment_reminder->subject = str_replace(
array_keys($replacements),
array_values($replacements),
$payment_reminder->subject
);
$payment_reminder->message = str_replace(
array_keys($replacements),
array_values($replacements),
$payment_reminder->message
);
return $payment_reminder;
}
public function sendReminderEmail($payment, $payment_reminder)
{
try {
$email = $payment->shopping_order->shopping_user->billing_email;
$subject = $payment_reminder->subject;
$message = $payment_reminder->message;
if(Util::isTestSystem()){
$email = config('app.checkout_test_mail');
}
if($payment->shopping_order->mode === 'test' || Util::isTestSystem()){
$bcc[] = config('app.checkout_test_mail');
}else{
$bcc[] = config('app.checkout_mail');
}
Mail::to($email)->bcc($bcc)->send(new PaymentReminderEmail($subject, $message, $payment->shopping_order));
return true;
} catch (\Exception $e) {
\Log::error('Fehler beim E-Mail-Versand: ' . $e->getMessage());
$this->createLog(
'email_exception',
"E-Mail Exception: " . $e->getMessage() . " für Payment ID: {$payment->id}",
'ShoppingOrder',
$payment->shopping_order_id,
5
);
return false;
}
}
/**
* Berechnet den Countdown bis zur nächsten Zahlungserinnerung
*/
public function getNextReminderCountdown($payment)
{
// Wenn noch keine Erinnerung gesendet wurde
if ($payment->reminder == 0) {
return null;
}
// Hole alle aktiven Erinnerungen für diesen Clearingtype
$payment_reminders = PaymentReminder::where('active', true)
->where('clearingtype', $payment->clearingtype)
->orderBy('interval', 'asc')
->get();
if ($payment_reminders->isEmpty()) {
return null;
}
// Wenn alle Erinnerungen bereits gesendet wurden
if ($payment->reminder >= $payment_reminders->count()) {
return [
'type' => 'completed',
'message' => 'Alle Erinnerungen gesendet',
'days_left' => 0
];
}
// Hole die nächste Erinnerung
$next_reminder = $payment_reminders[$payment->reminder];
// Berechne die Differenz zwischen aktuellem und nächstem Reminder
$current_reminder = $payment_reminders[$payment->reminder - 1];
$interval_difference = $next_reminder->interval - $current_reminder->interval;
// Berechne das Datum der nächsten Erinnerung
$next_reminder_date = Carbon::parse($payment->reminder_date)->addDays($interval_difference);
// Berechne die verbleibenden Tage
$days_left = Carbon::now()->diffInDays($next_reminder_date, false);
// Wenn die nächste Erinnerung bereits fällig ist
if ($days_left <= 0) {
return [
'type' => 'overdue',
'message' => 'Nächste Erinnerung fällig',
'days_left' => 0,
'next_reminder_date' => $next_reminder_date
];
}
return [
'type' => 'countdown',
'message' => 'Nächste Erinnerung in ' . $days_left . ' Tagen',
'days_left' => $days_left,
'next_reminder_date' => $next_reminder_date,
'next_reminder_interval' => $interval_difference
];
}
/**
* Hole alle Logs für Payment Reminder
*/
public function getPaymentReminderLogs($limit = 100, $paymentId = null, $action = null)
{
$query = Logger::where('channel', 'payment_reminder')
->orderBy('created_at', 'desc');
if ($paymentId) {
$query->where('model_id', $paymentId);
}
if ($action) {
$query->where('action', $action);
}
return $query->limit($limit)->get();
}
/**
* Hole Logs für einen spezifischen Payment
*/
public function getLogsForPayment($orderId)
{
return Logger::where('channel', 'payment_reminder')
->where('model_id', $orderId)
->orderBy('created_at', 'desc')
->get();
}
/**
* Hole Logs für einen spezifischen Zeitraum
*/
public function getLogsForDateRange($startDate, $endDate)
{
return Logger::where('channel', 'payment_reminder')
->whereBetween('created_at', [$startDate, $endDate])
->orderBy('created_at', 'desc')
->get();
}
/**
* Hole Statistiken für Payment Reminder Logs
*/
public function getLogStatistics($days = 30)
{
$startDate = Carbon::now()->subDays($days);
$stats = Logger::where('channel', 'payment_reminder')
->where('created_at', '>=', $startDate)
->selectRaw('action, level, COUNT(*) as count')
->groupBy('action', 'level')
->get();
$summary = [
'total_logs' => Logger::where('channel', 'payment_reminder')
->where('created_at', '>=', $startDate)
->count(),
'emails_sent' => Logger::where('channel', 'payment_reminder')
->where('action', 'email_sent')
->where('created_at', '>=', $startDate)
->count(),
'emails_failed' => Logger::where('channel', 'payment_reminder')
->where('action', 'email_exception')
->where('created_at', '>=', $startDate)
->count(),
'reminders_completed' => Logger::where('channel', 'payment_reminder')
->where('action', 'reminder_completed')
->where('created_at', '>=', $startDate)
->count(),
'actions_executed' => Logger::where('channel', 'payment_reminder')
->where('action', 'action_completed')
->where('created_at', '>=', $startDate)
->count(),
];
return [
'summary' => $summary,
'detailed_stats' => $stats
];
}
}

View file

@ -0,0 +1,201 @@
<?php
namespace App\Services;
use App\Models\ShoppingOrder;
use App\Models\ShoppingPayment;
use App\Models\UserPayCredit;
use App\Models\PaymentTransaction;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PaymentService
{
public static $txaction_art = [
'user_order' => "Vertriebspartner",
'customer_order' => "Kundenbestellung",
'user_for_customer' => "VP.Kundenbestellung",
];
// Konstanten für bessere Wartbarkeit
const CREDIT_STATUS_DEDUCTION = 2;
const CREDIT_STATUS_RETURN = 4;
const CREDIT_STATUS_CHARGED = 7;
const CREDIT_STATUS_REMOVED = 8;
const TRANSACTION_REQUEST = 'transaction';
const DEFAULT_TXID = 0;
const DEFAULT_USERID = 0;
/**
* Aktualisiert den Transaktionsstatus einer Bestellung
*
* @param int $orderId
* @param string $txaction
* @param int $paymentId
* @return bool
* @throws \Exception
*/
public static function updateTransactionStatus($orderId, $txaction, $paymentId)
{
// Validierung der Eingabeparameter
if (empty($orderId) || empty($txaction) || empty($paymentId)) {
throw new \InvalidArgumentException('Alle Parameter müssen angegeben werden');
}
return DB::transaction(function () use ($orderId, $txaction, $paymentId) {
$shopping_order = ShoppingOrder::findOrFail($orderId);
$shopping_payment = ShoppingPayment::findOrFail($paymentId);
// Prüfen ob sich der Status tatsächlich geändert hat
if ($shopping_payment->txaction === $txaction) {
return false;
}
// Guthaben-Logik für Partner-Center Bestellungen
self::handlePartnerCenterCredits($shopping_order, $txaction);
// PaymentTransaction erstellen
$paymentTransaction = self::createPaymentTransaction($shopping_payment, $txaction);
// Bestellung und Payment aktualisieren
self::updateOrderAndPayment($shopping_order, $shopping_payment, $txaction, $paymentTransaction);
// Paid-Action ausführen falls nötig
self::handlePaidAction($paymentTransaction, $shopping_order);
// Credit-Loading Logik
self::handleCreditLoading($shopping_order, $txaction);
// E-Mail versenden
self::sendStatusEmail($shopping_order, $shopping_payment, $paymentTransaction);
return true;
});
}
/**
* Behandelt Guthaben-Logik für Partner-Center Bestellungen
*/
private static function handlePartnerCenterCredits(ShoppingOrder $shoppingOrder, string $txaction): void
{
if (!$shoppingOrder->shopping_order_margin || $shoppingOrder->shopping_order_margin->from_payment_credit <= 0) {
return;
}
$lastUserPayCredit = self::getLastUserPayCredit($shoppingOrder->id, [self::CREDIT_STATUS_DEDUCTION, self::CREDIT_STATUS_RETURN]);
if (!$lastUserPayCredit) {
return;
}
// Status Keine Zahlung, Guthaben zurückführen
if ($txaction === 'non' && $lastUserPayCredit->status === self::CREDIT_STATUS_DEDUCTION) {
Payment::handelUserPayCredits($shoppingOrder, 'return');
}
// Status Zahlung, vorher gab es eine Storno, Guthaben abziehen
if ($lastUserPayCredit->status === self::CREDIT_STATUS_RETURN && in_array($txaction, ['open', 'paid'])) {
Payment::handelUserPayCredits($shoppingOrder, 'deduction');
}
}
/**
* Erstellt eine neue PaymentTransaction
*/
private static function createPaymentTransaction(ShoppingPayment $shoppingPayment, string $txaction): PaymentTransaction
{
return PaymentTransaction::create([
'shopping_payment_id' => $shoppingPayment->id,
'request' => self::TRANSACTION_REQUEST,
'txid' => self::DEFAULT_TXID,
'userid' => self::DEFAULT_USERID,
'status' => $shoppingPayment->clearingtype,
'transmitted_data' => null,
'txaction' => $txaction,
'mode' => $shoppingPayment->mode,
]);
}
/**
* Aktualisiert Bestellung und Payment
*/
private static function updateOrderAndPayment(ShoppingOrder $shoppingOrder, ShoppingPayment $shoppingPayment, string $txaction, PaymentTransaction $paymentTransaction): void
{
$shoppingOrder->txaction = $txaction;
$shoppingOrder->paid = $paymentTransaction->txaction === 'paid';
$shoppingOrder->save();
$shoppingPayment->txaction = $txaction;
$shoppingPayment->save();
}
/**
* Führt Paid-Action aus falls nötig
*/
private static function handlePaidAction(PaymentTransaction $paymentTransaction, ShoppingOrder $shoppingOrder): void
{
if ($paymentTransaction->status === 'vor' && $paymentTransaction->txaction === 'paid') {
Payment::paymentStatusPaidAction($shoppingOrder, true);
}
}
/**
* Behandelt Credit-Loading Logik
*/
private static function handleCreditLoading(ShoppingOrder $shoppingOrder, string $txaction): void
{
if (!$shoppingOrder->shopping_user || $shoppingOrder->shopping_user->is_for !== 'cr') {
return;
}
$lastUserPayCredit = self::getLastUserPayCredit($shoppingOrder->id, [self::CREDIT_STATUS_CHARGED, self::CREDIT_STATUS_REMOVED]);
if (!$lastUserPayCredit) {
return;
}
// Status Keine Zahlung, Guthaben abziehen
if ($txaction === 'non' && $lastUserPayCredit->status === self::CREDIT_STATUS_CHARGED) {
Payment::handelUserPayChargingCredits($shoppingOrder, 'remove');
}
// Status Zahlung, vorher gab es eine Storno, Guthaben wieder aufladen
if ($lastUserPayCredit->status === self::CREDIT_STATUS_REMOVED && $txaction === 'paid') {
Payment::handelUserPayChargingCredits($shoppingOrder, 'add');
}
}
/**
* Sendet Status-E-Mail
*/
private static function sendStatusEmail(ShoppingOrder $shoppingOrder, ShoppingPayment $shoppingPayment, PaymentTransaction $paymentTransaction): void
{
$emailData = [
'mode' => $paymentTransaction->mode,
'txaction' => $paymentTransaction->txaction,
'send_link' => false,
];
try {
Payment::paymentStatusSendMail($shoppingOrder, $shoppingPayment, $emailData);
} catch (\Exception $e) {
Log::error('Fehler beim Senden der Status-E-Mail', [
'order_id' => $shoppingOrder->id,
'payment_id' => $shoppingPayment->id,
'error' => $e->getMessage()
]);
}
}
/**
* Holt den letzten UserPayCredit Eintrag
*/
private static function getLastUserPayCredit(int $orderId, array $statuses): ?UserPayCredit
{
return UserPayCredit::where('shopping_order_id', $orderId)
->whereIn('status', $statuses)
->orderBy('id', 'DESC')
->first();
}
}

View file

@ -44,7 +44,11 @@ class UserMarign
return $sum_net_amount;
}
public static function getMontlyAmount(User $user, $date = null, $format = false){
public static function getMontlyAmount($user, $date = null, $format = false){
if(!$user instanceof User){
return 0;
}
$now = $date ? Carbon::parse($date) : Carbon::now();
$startDay = $now->startOfMonth()->toDateString();
@ -202,7 +206,8 @@ class UserMarign
->whereOutPaid(false)
->whereCancellation(false)
->whereMarginPaid(false)
->whereNotNull('margin_pending_to');
->whereNotNull('margin_pending_to')
->whereIn('status', [7,8]);
if ($isPending) {
$query->where('margin_pending_to', '>=', Carbon::now());

View file

@ -3,6 +3,7 @@ namespace App\Services;
use Yard;
use App\User;
use Illuminate\Support\Str;
use App\Models\PromotionUser;
use App\Models\ShippingCountry;
@ -18,7 +19,7 @@ class UserService
public static function createConfirmationCode() {
$unique = false;
do{
$confirmation_code = str_random(30);
$confirmation_code = Str::random(30);
if(User::where('confirmation_code', '=', $confirmation_code)->count() == 0){
$unique = true;
}

View file

@ -13,7 +13,7 @@ class Util
public static function getToken()
{
return hash_hmac('sha256', str_random(40), config('app.key'));
return hash_hmac('sha256', Str::random(40), config('app.key'));
}
public static function uuidToken()
@ -127,7 +127,7 @@ class Util
return false;
}
public static function setUserHistoryValue($values = [], $identifier){
public static function setUserHistoryValue($values, $identifier){
if($user_history = self::getUserHistory($identifier)){
foreach ($values as $key=>$val){
$user_history->{$key} = $val;
@ -171,6 +171,13 @@ class Util
return false;
}
public static function isTestSystem(){
if(config('app.debug')){
return true;
}
return false;
}
public static function isPromotionUrl($debug = false){
if($debug && config('app.debug')){
return false;