commit 08-2025
This commit is contained in:
parent
9b54eb0512
commit
02f2a4c23e
184 changed files with 31653 additions and 22327 deletions
18
.env
18
.env
|
|
@ -12,12 +12,12 @@ APP_PROMO_DOMAIN=testemich.test
|
||||||
APP_SHOP_URL=https://grueneseele.test
|
APP_SHOP_URL=https://grueneseele.test
|
||||||
APP_SHOP_DOMAIN=grueneseele.test
|
APP_SHOP_DOMAIN=grueneseele.test
|
||||||
|
|
||||||
APP_CHECKOUT_MAIL=register@adametz.media
|
APP_CHECKOUT_MAIL=kevin.adametz@me.com
|
||||||
APP_CHECKOUT_TEST_MAIL=register@adametz.media
|
APP_CHECKOUT_TEST_MAIL=register@adametz.media
|
||||||
APP_INFO_MAIL=register@adametz.media
|
APP_INFO_MAIL=kevin.adametz@me.com
|
||||||
APP_INFO_TEST_MAIL=register@adametz.media
|
APP_INFO_TEST_MAIL=register@adametz.media
|
||||||
EXCEPTION_MAIL=exception@adametz.media
|
EXCEPTION_MAIL=exception@adametz.media
|
||||||
|
LOGISTIC_MAIL=kevin.adametz@me.com
|
||||||
APP_MAIN_TAX = 1.19
|
APP_MAIN_TAX = 1.19
|
||||||
APP_MAIN_TAX_RATE = 19
|
APP_MAIN_TAX_RATE = 19
|
||||||
|
|
||||||
|
|
@ -54,11 +54,13 @@ REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
MAIL_DRIVER=smtp
|
MAIL_DRIVER=smtp
|
||||||
MAIL_HOST=w017f6e4.kasserver.com
|
MAIL_HOST=w017e534.kasserver.com
|
||||||
MAIL_PORT=587
|
MAIL_PORT=587
|
||||||
MAIL_USERNAME=m04a9fbc
|
MAIL_USERNAME=m0496c96
|
||||||
MAIL_PASSWORD=3tQ72oCHZgncCTpK
|
MAIL_PASSWORD=mZtVp7WQcs6DC3hf
|
||||||
MAIL_ENCRYPTION=null
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS=dev@adametz.media
|
||||||
|
MAIL_FROM_NAME="DEV Grüne Seele"
|
||||||
|
|
||||||
#MAIL_MAILER=smtp
|
#MAIL_MAILER=smtp
|
||||||
#MAIL_HOST=s182.goserver.host
|
#MAIL_HOST=s182.goserver.host
|
||||||
|
|
@ -66,8 +68,8 @@ MAIL_ENCRYPTION=null
|
||||||
#MAIL_USERNAME=web28p3
|
#MAIL_USERNAME=web28p3
|
||||||
#MAIL_PASSWORD=WeE2bmI9GjB7pDgi
|
#MAIL_PASSWORD=WeE2bmI9GjB7pDgi
|
||||||
#MAIL_ENCRYPTION=""
|
#MAIL_ENCRYPTION=""
|
||||||
MAIL_FROM_ADDRESS=partner@gruene-seele.bio
|
#MAIL_FROM_ADDRESS=partner@gruene-seele.bio
|
||||||
MAIL_FROM_NAME="GRÜNE SEELE Naturkosmetik"
|
#MAIL_FROM_NAME="GRÜNE SEELE Naturkosmetik"
|
||||||
|
|
||||||
RECAPTCHA_SITE_KEY="6LcGr_kqAAAAAOnz-L6IIBC_fTzJ7siTheZgFVMY"
|
RECAPTCHA_SITE_KEY="6LcGr_kqAAAAAOnz-L6IIBC_fTzJ7siTheZgFVMY"
|
||||||
RECAPTCHA_SECRET_KEY="6LcGr_kqAAAAAKBZVoy37ski0Gl54jenWOlrbc9z"
|
RECAPTCHA_SECRET_KEY="6LcGr_kqAAAAAKBZVoy37ski0Gl54jenWOlrbc9z"
|
||||||
|
|
|
||||||
4289
.phpstorm.meta.php
4289
.phpstorm.meta.php
File diff suppressed because it is too large
Load diff
249
PAYMENT_REMINDER_CRON.md
Normal file
249
PAYMENT_REMINDER_CRON.md
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
# Payment Reminder Cron-Job Einrichtung
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
Der `PaymentsReminders` Command automatisiert das Senden von Zahlungserinnerungen basierend auf den konfigurierten Intervallen in der Datenbank.
|
||||||
|
|
||||||
|
## Command ausführen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php artisan payments:reminders
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cron-Job Konfiguration
|
||||||
|
|
||||||
|
### 1. Crontab öffnen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Cron-Job hinzufügen
|
||||||
|
|
||||||
|
**Täglich um 9:00 Uhr:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
0 9 * * * cd /path/to/your/project && php artisan payments:reminders >> /dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stündlich:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
0 * * * * cd /path/to/your/project && php artisan payments:reminders >> /dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alle 6 Stunden:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
0 */6 * * * cd /path/to/your/project && php artisan payments:reminders >> /dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Cron-Job testen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Teste den Command manuell
|
||||||
|
php artisan payments:reminders
|
||||||
|
|
||||||
|
# Prüfe die Logs
|
||||||
|
tail -f storage/logs/laravel.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Funktionsweise
|
||||||
|
|
||||||
|
### 1. Intervall-basierte Verarbeitung
|
||||||
|
|
||||||
|
- Der Command holt alle aktiven `PaymentReminder` aus der Datenbank
|
||||||
|
- Gruppiert sie nach `clearingtype` (z.B. 'invoice', 'prepayment')
|
||||||
|
- Verwendet das kleinste Intervall pro `clearingtype`
|
||||||
|
|
||||||
|
### 2. Zahlungsprüfung
|
||||||
|
|
||||||
|
- Sucht offene Zahlungen, die älter als das konfigurierte Intervall sind
|
||||||
|
- Berücksichtigt nur die neueste Zahlung pro Bestellung
|
||||||
|
- Prüft nur Live-Zahlungen (nicht Test)
|
||||||
|
|
||||||
|
### 3. Erinnerungslogik
|
||||||
|
|
||||||
|
- **Erste Erinnerung**: Nach X Tagen ab Bestelldatum
|
||||||
|
- **Weitere Erinnerungen**: Nach Y Tagen ab letzter Erinnerung
|
||||||
|
- Stoppt wenn alle konfigurierten Erinnerungen gesendet wurden
|
||||||
|
|
||||||
|
### 4. Automatische Aktionen
|
||||||
|
|
||||||
|
- E-Mail-Versand mit Platzhalter-Ersetzung
|
||||||
|
- Optional: Bestellung auf "Storniert" setzen
|
||||||
|
- Optional: Payment auf "non" Status setzen
|
||||||
|
- Logging aller Aktivitäten
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
### Command-Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Live-Logs während der Ausführung
|
||||||
|
php artisan payments:reminders
|
||||||
|
|
||||||
|
# Beispiel-Output:
|
||||||
|
RUN Command Payments Reminders: 15.12.2024 09:00
|
||||||
|
=== STARTE PAYMENT REMINDERS ===
|
||||||
|
Gefundene aktive PaymentReminder: 3
|
||||||
|
Gefundene clearingtypes mit kleinsten Intervallen:
|
||||||
|
- invoice: 7 Tage
|
||||||
|
- prepayment: 3 Tage
|
||||||
|
--- Verarbeite clearingtype: invoice mit Intervall: 7 Tage ---
|
||||||
|
Suche Zahlungen vor: 08.12.2024 09:00:00
|
||||||
|
Gefundene offene Zahlungen für invoice: 5
|
||||||
|
Verarbeite Order ID: 12345, Created: 05.12.2024 10:30:00, Amount: 5000, Reminder: 0
|
||||||
|
📧 Sende Erinnerung...
|
||||||
|
✅ Erinnerung erfolgreich gesendet
|
||||||
|
=== PAYMENT REMINDERS ABGESCHLOSSEN ===
|
||||||
|
Ausführungszeit: 2.34 Sekunden
|
||||||
|
Statistiken:
|
||||||
|
- Gesamt verarbeitet: 5
|
||||||
|
- Erinnerungen gesendet: 3
|
||||||
|
- Fehler: 0
|
||||||
|
- Übersprungen: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Laravel-Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs in storage/logs/laravel.log
|
||||||
|
tail -f storage/logs/laravel.log | grep "Payment reminder"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
### PaymentReminder Einstellungen
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Beispiel-Konfiguration
|
||||||
|
INSERT INTO payment_reminders (clearingtype, interval, subject, message, action, active) VALUES
|
||||||
|
('invoice', 7, 'Zahlungserinnerung - Bestellung {order_number}', 'Sehr geehrte/r {billing_first_name}...', NULL, 1),
|
||||||
|
('invoice', 14, '2. Zahlungserinnerung - Bestellung {order_number}', 'Sehr geehrte/r {billing_first_name}...', NULL, 1),
|
||||||
|
('invoice', 21, 'Letzte Zahlungserinnerung - Bestellung {order_number}', 'Sehr geehrte/r {billing_first_name}...', 'set_order_status_cancelled', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Platzhalter
|
||||||
|
|
||||||
|
- `{billing_first_name}` - Vorname
|
||||||
|
- `{billing_last_name}` - Nachname
|
||||||
|
- `{order_number}` - Bestellnummer
|
||||||
|
- `{order_date}` - Bestelldatum
|
||||||
|
- `{order_total}` - Bestellsumme
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
### 1. Log-Statistiken
|
||||||
|
|
||||||
|
- Admin-Bereich: `/admin/payments/reminder/logs`
|
||||||
|
- Zeigt Statistiken der letzten 7, 30 und 90 Tage
|
||||||
|
- Filter nach Order ID, Aktion und Datum
|
||||||
|
|
||||||
|
### 2. Erfolgsrate
|
||||||
|
|
||||||
|
- E-Mails gesendet vs. Fehler
|
||||||
|
- Aktionen ausgeführt
|
||||||
|
- Übersprungene Erinnerungen
|
||||||
|
|
||||||
|
### 3. Performance
|
||||||
|
|
||||||
|
- Ausführungszeit pro Lauf
|
||||||
|
- Anzahl verarbeiteter Zahlungen
|
||||||
|
- Speicherverbrauch
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Häufige Probleme
|
||||||
|
|
||||||
|
**1. Command läuft nicht**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe PHP-Pfad
|
||||||
|
which php
|
||||||
|
|
||||||
|
# Prüfe Projekt-Pfad
|
||||||
|
pwd
|
||||||
|
|
||||||
|
# Teste Command manuell
|
||||||
|
php artisan payments:reminders
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Keine E-Mails werden gesendet**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe Mail-Konfiguration
|
||||||
|
php artisan config:cache
|
||||||
|
|
||||||
|
# Prüfe Logs
|
||||||
|
tail -f storage/logs/laravel.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Falsche Intervalle**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe PaymentReminder-Konfiguration
|
||||||
|
php artisan tinker
|
||||||
|
>>> App\Models\PaymentReminder::where('active', true)->get()
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Cron-Job läuft nicht**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe Crontab
|
||||||
|
crontab -l
|
||||||
|
|
||||||
|
# Prüfe Cron-Logs
|
||||||
|
sudo tail -f /var/log/cron
|
||||||
|
|
||||||
|
# Teste mit absoluten Pfaden
|
||||||
|
0 9 * * * /usr/bin/php /path/to/project/artisan payments:reminders
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sicherheit
|
||||||
|
|
||||||
|
### 1. Berechtigungen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stelle sicher, dass der Webserver-Benutzer Schreibrechte hat
|
||||||
|
chown -R www-data:www-data storage/logs
|
||||||
|
chmod -R 755 storage/logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Log-Rotation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Konfiguriere Log-Rotation in /etc/logrotate.d/laravel
|
||||||
|
/path/to/project/storage/logs/*.log {
|
||||||
|
daily
|
||||||
|
missingok
|
||||||
|
rotate 52
|
||||||
|
compress
|
||||||
|
notifempty
|
||||||
|
create 644 www-data www-data
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Backup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup der PaymentReminder-Konfiguration
|
||||||
|
mysqldump -u username -p database payment_reminders > payment_reminders_backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance-Optimierung
|
||||||
|
|
||||||
|
### 1. Batch-Verarbeitung
|
||||||
|
|
||||||
|
- Der Command verarbeitet Zahlungen in Batches
|
||||||
|
- Verwendet Datenbank-Indizes für bessere Performance
|
||||||
|
|
||||||
|
### 2. Memory-Management
|
||||||
|
|
||||||
|
- Garbage Collection nach jeder Zahlung
|
||||||
|
- Begrenzte Anzahl von Logs
|
||||||
|
|
||||||
|
### 3. Timeout-Handling
|
||||||
|
|
||||||
|
- Lange Ausführungen werden abgebrochen
|
||||||
|
- Fehler werden geloggt und übersprungen
|
||||||
34807
_ide_helper.php
34807
_ide_helper.php
File diff suppressed because it is too large
Load diff
252
app/Console/Commands/PaymentsReminders.php
Normal file
252
app/Console/Commands/PaymentsReminders.php
Normal 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()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,13 +24,22 @@ class Kernel extends ConsoleKernel
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
$schedule->command('payments:accounts')
|
/*$schedule->command('payments:accounts')
|
||||||
->sendOutputTo(storage_path('logs/cron.log'))
|
->sendOutputTo(storage_path('logs/cron.log'))
|
||||||
->appendOutputTo(storage_path('logs/cron-history.log'))
|
->appendOutputTo(storage_path('logs/cron-history.log'))
|
||||||
->emailOutputOnFailure(config('app.exception_mail'))
|
->emailOutputOnFailure(config('app.exception_mail'))
|
||||||
->onFailure(function () {
|
->onFailure(function () {
|
||||||
\Log::error('Payments:accounts command failed');
|
\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');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ namespace App\Exceptions;
|
||||||
|
|
||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||||
|
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
|
||||||
|
|
||||||
class Handler extends ExceptionHandler
|
class Handler extends ExceptionHandler
|
||||||
{
|
{
|
||||||
|
|
@ -36,6 +39,9 @@ class Handler extends ExceptionHandler
|
||||||
*/
|
*/
|
||||||
public function report(Throwable $exception)
|
public function report(Throwable $exception)
|
||||||
{
|
{
|
||||||
|
if ($this->shouldReport($exception)) {
|
||||||
|
$this->sendEmail($exception);
|
||||||
|
}
|
||||||
parent::report($exception);
|
parent::report($exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,4 +58,35 @@ class Handler extends ExceptionHandler
|
||||||
{
|
{
|
||||||
return parent::render($request, $exception);
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
41
app/Http/Controllers/Admin/PaymentReminderController.php
Normal file
41
app/Http/Controllers/Admin/PaymentReminderController.php
Normal 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'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -27,7 +27,7 @@ class ModalController extends Controller
|
||||||
if(Request::ajax()){
|
if(Request::ajax()){
|
||||||
if($data['action'] === 'shopping-order-change-member'){
|
if($data['action'] === 'shopping-order-change-member'){
|
||||||
$value = ShoppingOrder::find($data['id']);
|
$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();
|
$ret = view("admin.modal.member", compact('value', 'data', 'route'))->render();
|
||||||
}
|
}
|
||||||
if($data['action'] === 'shopping-user-change-member'){
|
if($data['action'] === 'shopping-user-change-member'){
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ class PaymentInvoiceController extends Controller
|
||||||
|
|
||||||
return \DataTables::eloquent($query)
|
return \DataTables::eloquent($query)
|
||||||
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
|
->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) {
|
->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return $ShoppingOrder->getFormattedTotalShipping()." €";
|
return $ShoppingOrder->getFormattedTotalShipping()." €";
|
||||||
|
|
|
||||||
147
app/Http/Controllers/PaymentReminderController.php
Normal file
147
app/Http/Controllers/PaymentReminderController.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Request;
|
use Request;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\UserShop;
|
|
||||||
use App\Services\Payment;
|
use App\Services\Payment;
|
||||||
use App\Models\ShoppingUser;
|
use App\Models\ShoppingUser;
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
|
|
@ -13,6 +12,7 @@ use App\Models\ShoppingPayment;
|
||||||
use App\Models\PaymentTransaction;
|
use App\Models\PaymentTransaction;
|
||||||
use App\Services\CustomerPriority;
|
use App\Services\CustomerPriority;
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Repositories\InvoiceRepository;
|
||||||
|
use App\Services\PaymentService;
|
||||||
|
|
||||||
class SalesController extends Controller
|
class SalesController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -21,7 +21,167 @@ class SalesController extends Controller
|
||||||
$this->middleware('admin');
|
$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'){
|
if(Request::get('reset') === 'filter'){
|
||||||
return redirect(route('admin_sales_users'));
|
return redirect(route('admin_sales_users'));
|
||||||
|
|
@ -105,7 +265,7 @@ class SalesController extends Controller
|
||||||
if(Request::get('reset') === 'filter'){
|
if(Request::get('reset') === 'filter'){
|
||||||
set_user_attr('filter_txaction', null);
|
set_user_attr('filter_txaction', null);
|
||||||
set_user_attr('filter_member_id', 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();
|
$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 = [
|
$data = [
|
||||||
|
|
@ -141,7 +301,7 @@ class SalesController extends Controller
|
||||||
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
||||||
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
|
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
|
||||||
\Session()->flash('alert-save', true);
|
\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'){
|
if($data['action']==='shopping-user-is-like-member'){
|
||||||
|
|
@ -169,7 +329,7 @@ class SalesController extends Controller
|
||||||
'isAdmin' => true,
|
'isAdmin' => true,
|
||||||
'isView' => 'sales_customer',
|
'isView' => 'sales_customer',
|
||||||
];
|
];
|
||||||
return view('admin.sales.customer_detail', $data);
|
return view('admin.sales._detail', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function customersDatatable(){
|
public function customersDatatable(){
|
||||||
|
|
@ -192,7 +352,7 @@ class SalesController extends Controller
|
||||||
|
|
||||||
return \DataTables::eloquent($query)
|
return \DataTables::eloquent($query)
|
||||||
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
|
->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) {
|
->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return $ShoppingOrder->created_at->format("d.m.Y");
|
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"
|
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-id="'.$ShoppingOrder->shopping_user->id.'"
|
||||||
data-action="shopping-user-is-like-member"
|
data-action="shopping-user-is-like-member"
|
||||||
data-back="'.route('admin_sales_customers').'"
|
data-back="'.route('admin_sales').'"
|
||||||
data-modal="modal-xl"
|
data-modal="modal-xl"
|
||||||
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>';
|
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')
|
->orderColumn('total_shipping', 'total_shipping $1')
|
||||||
->rawColumns(['id', 'member_id', 'txaction', 'user_shop_id', 'payment_for', 'shipped'])
|
->rawColumns(['id', 'member_id', 'txaction', 'user_shop_id', 'payment_for', 'shipped'])
|
||||||
->make(true);
|
->make(true);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public function store(){
|
public function store(){
|
||||||
$data = Request::all();
|
$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'])){
|
if($data['action'] === 'store_txaction' && isset($data['txaction']) && isset($data['payment_id'])){
|
||||||
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
PaymentService::updateTransactionStatus($data['id'], $data['txaction'], $data['payment_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -391,9 +495,21 @@ class SalesController extends Controller
|
||||||
}else{
|
}else{
|
||||||
$user_invoice = $invoice_repo->create($data);
|
$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]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +43,6 @@ class SalesController extends Controller
|
||||||
|
|
||||||
public function download()
|
public function download()
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->setFilterVars();
|
$this->setFilterVars();
|
||||||
|
|
||||||
if (Request::get('action') === "filter") {
|
if (Request::get('action') === "filter") {
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class PromotionController extends Controller
|
||||||
if(isset($data['action']) && $data['action'] === 'save-user-promotion'){
|
if(isset($data['action']) && $data['action'] === 'save-user-promotion'){
|
||||||
$rules = array(
|
$rules = array(
|
||||||
'name' => 'required',
|
'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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
||||||
|
|
@ -107,7 +107,7 @@ class PromotionController extends Controller
|
||||||
$unique .= ','.$data['puid'].',id';
|
$unique .= ','.$data['puid'].',id';
|
||||||
}
|
}
|
||||||
$rules = array(
|
$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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -54,7 +54,7 @@ class ShopController extends Controller
|
||||||
if(isset($data['action']) && $data['action'] === 'save-user-shop'){
|
if(isset($data['action']) && $data['action'] === 'save-user-shop'){
|
||||||
$rules = array(
|
$rules = array(
|
||||||
'name' => 'required',
|
'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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
||||||
|
|
@ -84,7 +84,7 @@ class ShopController extends Controller
|
||||||
$unique .= ','.$data['usid'].',id';
|
$unique .= ','.$data['usid'].',id';
|
||||||
}
|
}
|
||||||
$rules = array(
|
$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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
$profanity = \App\Models\Setting::getContentBySlug('promotion_user_url_profanity');
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ class UserShopController extends Controller
|
||||||
|
|
||||||
if(Request::get('shop_submit') == 'check'){
|
if(Request::get('shop_submit') == 'check'){
|
||||||
$rules = array(
|
$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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
if(in_array($value, config('profanity.full_word_check'))){
|
if(in_array($value, config('profanity.full_word_check'))){
|
||||||
|
|
@ -291,7 +291,7 @@ class UserShopController extends Controller
|
||||||
if(Request::get('shop_submit') == 'action') {
|
if(Request::get('shop_submit') == 'action') {
|
||||||
|
|
||||||
$rules = array(
|
$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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
if(in_array($value, config('profanity.full_word_check'))){
|
if(in_array($value, config('profanity.full_word_check'))){
|
||||||
|
|
@ -381,7 +381,7 @@ class UserShopController extends Controller
|
||||||
public function checkUserShopName(){
|
public function checkUserShopName(){
|
||||||
|
|
||||||
$rules = array(
|
$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) {
|
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
|
||||||
if(in_array($value, config('profanity.full_word_check'))){
|
if(in_array($value, config('profanity.full_word_check'))){
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,15 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Mail\MailActivateUser;
|
||||||
use App\User;
|
use App\User;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Validator;
|
|
||||||
use Request;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
use App\Mail\MailActivateUser;
|
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Request;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
class UserUpdateEmailController extends Controller
|
class UserUpdateEmailController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -152,7 +153,7 @@ class UserUpdateEmailController extends Controller
|
||||||
|
|
||||||
protected function getToken()
|
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)
|
public function createActivation($user, array $data)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class Kernel extends HttpKernel
|
||||||
*/
|
*/
|
||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
\Fruitcake\Cors\HandleCors::class,
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
\App\Http\Middleware\TrimStrings::class,
|
\App\Http\Middleware\TrimStrings::class,
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
|
||||||
|
|
||||||
class TrustProxies extends Middleware
|
class TrustProxies extends Middleware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The trusted proxies for this application.
|
* The trusted proxies for this application.
|
||||||
*
|
*
|
||||||
* @var array|string
|
* @var array|string|null
|
||||||
*/
|
*/
|
||||||
protected $proxies;
|
protected $proxies;
|
||||||
|
|
||||||
|
|
@ -19,5 +19,10 @@ class TrustProxies extends Middleware
|
||||||
*
|
*
|
||||||
* @var int
|
* @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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
188
app/Libraries/MyPDFMerger.php
Normal file
188
app/Libraries/MyPDFMerger.php
Normal 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
87
app/Mail/MailLogistic.php
Normal 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
59
app/Mail/MailLogitic.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
app/Mail/PaymentReminderEmail.php
Normal file
60
app/Mail/PaymentReminderEmail.php
Normal 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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
app/Models/PaymentReminder.php
Normal file
57
app/Models/PaymentReminder.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -105,6 +105,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value)
|
||||||
* @property array|null $delivery
|
* @property array|null $delivery
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDelivery($value)
|
* @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
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class ShoppingOrder extends Model
|
class ShoppingOrder extends Model
|
||||||
|
|
@ -138,6 +140,7 @@ class ShoppingOrder extends Model
|
||||||
'paid',
|
'paid',
|
||||||
'invoice',
|
'invoice',
|
||||||
'delivery',
|
'delivery',
|
||||||
|
'user_white_label',
|
||||||
'invoice_number',
|
'invoice_number',
|
||||||
'txaction',
|
'txaction',
|
||||||
'wp_invoice_path',
|
'wp_invoice_path',
|
||||||
|
|
@ -146,7 +149,7 @@ class ShoppingOrder extends Model
|
||||||
'shipped',
|
'shipped',
|
||||||
'shipped_at',
|
'shipped_at',
|
||||||
'shipping_option',
|
'shipping_option',
|
||||||
'tracking'
|
'tracking',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
|
@ -154,6 +157,7 @@ class ShoppingOrder extends Model
|
||||||
'invoice' => 'array',
|
'invoice' => 'array',
|
||||||
'delivery' => 'array',
|
'delivery' => 'array',
|
||||||
'shipped_at' => 'datetime',
|
'shipped_at' => 'datetime',
|
||||||
|
'user_white_label' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $shippedTypes = [
|
public static $shippedTypes = [
|
||||||
|
|
@ -161,6 +165,7 @@ class ShoppingOrder extends Model
|
||||||
1 => 'in Bearbeitung',
|
1 => 'in Bearbeitung',
|
||||||
2 => 'versendet',
|
2 => 'versendet',
|
||||||
3 => 'abgeschlossen',
|
3 => 'abgeschlossen',
|
||||||
|
5 => 'Wartestellung',
|
||||||
4 => 'Abholung',
|
4 => 'Abholung',
|
||||||
10 => 'storniert'
|
10 => 'storniert'
|
||||||
];
|
];
|
||||||
|
|
@ -213,6 +218,7 @@ class ShoppingOrder extends Model
|
||||||
2 => 'success',
|
2 => 'success',
|
||||||
3 => 'secondary',
|
3 => 'secondary',
|
||||||
4 => 'success',
|
4 => 'success',
|
||||||
|
5 => 'warning-dark',
|
||||||
10 => 'danger',
|
10 => 'danger',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,14 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderMargin wherePartnerCommissionPendingTo($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderMargin wherePartnerCommissionPendingTo($value)
|
||||||
* @property int|null $user_credit_id
|
* @property int|null $user_credit_id
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderMargin whereUserCreditId($value)
|
* @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
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class ShoppingOrderMargin extends Model
|
class ShoppingOrderMargin extends Model
|
||||||
|
|
@ -113,7 +121,12 @@ class ShoppingOrderMargin extends Model
|
||||||
|
|
||||||
public static $statusTypes = [
|
public static $statusTypes = [
|
||||||
0 => 'user order',
|
0 => 'user order',
|
||||||
1 => '',
|
1 => 'Registrierung',
|
||||||
|
2 => 'Mitgliedschaft',
|
||||||
|
3 => 'Guthabenaufladung',
|
||||||
|
4 => 'VP.Bestellung Abholung',
|
||||||
|
5 => 'VP.Bestellung Lieferung',
|
||||||
|
6 => 'VP.Kundenbestellung',
|
||||||
7 => 'from promotion',
|
7 => 'from promotion',
|
||||||
8 => 'from shop',
|
8 => 'from shop',
|
||||||
9 => 'storniert'
|
9 => 'storniert'
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,18 @@ class ShoppingPayment extends Model
|
||||||
'reference',
|
'reference',
|
||||||
'amount',
|
'amount',
|
||||||
'currency',
|
'currency',
|
||||||
|
'status',
|
||||||
|
'reminder',
|
||||||
|
'reminder_date',
|
||||||
|
'txaction',
|
||||||
'mode'
|
'mode'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'reminder' => 'integer',
|
||||||
|
'reminder_date' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
public function shopping_order()
|
public function shopping_order()
|
||||||
{
|
{
|
||||||
|
|
@ -91,6 +100,7 @@ class ShoppingPayment extends Model
|
||||||
if($this->clearingtype === 'non') {
|
if($this->clearingtype === 'non') {
|
||||||
return 'keine';
|
return 'keine';
|
||||||
}
|
}
|
||||||
|
return 'keine';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentAmount(){
|
public function getPaymentAmount(){
|
||||||
|
|
|
||||||
72
app/Policies/ModelPolicy.php
Executable file
72
app/Policies/ModelPolicy.php
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
|
@ -13,7 +14,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
//
|
Schema::defaultStringLength(191);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,6 +24,10 @@ class AppServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
//
|
|
||||||
|
if ($this->app->environment() !== 'production') {
|
||||||
|
$this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
|
||||||
|
}
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
use Laravel\Passport\Passport;
|
use Laravel\Passport\Passport;
|
||||||
|
|
||||||
|
|
||||||
class AuthServiceProvider extends ServiceProvider
|
class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,7 +14,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $policies = [
|
protected $policies = [
|
||||||
// 'App\Model' => 'App\Policies\ModelPolicy',
|
'App\Model' => 'App\Policies\ModelPolicy',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -26,7 +25,12 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
$this->registerPolicies();
|
$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));
|
||||||
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ class ContractPDFRepository extends BaseRepository {
|
||||||
$filename = "Vertriebspartnervertrag.pdf";
|
$filename = "Vertriebspartnervertrag.pdf";
|
||||||
Storage::disk($this->disk)->put($this->dir.$filename, $pdf->Output('S'));
|
Storage::disk($this->disk)->put($this->dir.$filename, $pdf->Output('S'));
|
||||||
$size = Storage::disk($this->disk)->size($this->dir.$filename);
|
$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([
|
File::create([
|
||||||
'user_id' => $this->model->id,
|
'user_id' => $this->model->id,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class CreditRepository extends BaseRepository {
|
||||||
if(!Storage::disk('public')->exists( $dir )){
|
if(!Storage::disk('public')->exists( $dir )){
|
||||||
Storage::disk('public')->makeDirectory($dir); //creates directory
|
Storage::disk('public')->makeDirectory($dir); //creates directory
|
||||||
}
|
}
|
||||||
$path = Storage::disk('public')->getAdapter()->getPathPrefix();
|
$path = Storage::disk('public')->path('');
|
||||||
$filename = Credit::makeCreditFilename($credit_number);
|
$filename = Credit::makeCreditFilename($credit_number);
|
||||||
|
|
||||||
$pdf->save($path.$dir.$filename);
|
$pdf->save($path.$dir.$filename);
|
||||||
|
|
@ -87,7 +87,7 @@ class CreditRepository extends BaseRepository {
|
||||||
private function finishUserCredit($user_credit){
|
private function finishUserCredit($user_credit){
|
||||||
//next number
|
//next number
|
||||||
Credit::makeNextCreditNumber();
|
Credit::makeNextCreditNumber();
|
||||||
//Partner Provision
|
//Partner Provision shopping order margin
|
||||||
$ShoppingOrderMargins = UserMarign::getPartnerCommissionItems($this->model->id, false);
|
$ShoppingOrderMargins = UserMarign::getPartnerCommissionItems($this->model->id, false);
|
||||||
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
|
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
|
||||||
$ShoppingOrderMargin->partner_commission_paid = true;
|
$ShoppingOrderMargin->partner_commission_paid = true;
|
||||||
|
|
@ -96,7 +96,7 @@ class CreditRepository extends BaseRepository {
|
||||||
$ShoppingOrderMargin->save();
|
$ShoppingOrderMargin->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Shop Provision
|
//Shop Provision shopping order margin
|
||||||
$ShoppingOrderMargins = UserMarign::getShopCommissionItems($this->model->id, false);
|
$ShoppingOrderMargins = UserMarign::getShopCommissionItems($this->model->id, false);
|
||||||
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
|
foreach($ShoppingOrderMargins as $ShoppingOrderMargin){
|
||||||
$ShoppingOrderMargin->margin_paid = true;
|
$ShoppingOrderMargin->margin_paid = true;
|
||||||
|
|
@ -105,7 +105,7 @@ class CreditRepository extends BaseRepository {
|
||||||
$ShoppingOrderMargin->save();
|
$ShoppingOrderMargin->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Hinzugefügte Provision
|
//Hinzugefügte Provision user credit margin
|
||||||
$UserCreditMargins = UserMarign::getUserCreditMarginByUserID($this->model->id);
|
$UserCreditMargins = UserMarign::getUserCreditMarginByUserID($this->model->id);
|
||||||
foreach($UserCreditMargins as $UserCreditMargin){
|
foreach($UserCreditMargins as $UserCreditMargin){
|
||||||
$UserCreditMargin->paid = true; //wurde ausgezahlt
|
$UserCreditMargin->paid = true; //wurde ausgezahlt
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class InvoiceRepository extends BaseRepository {
|
||||||
private $delivery_dir;
|
private $delivery_dir;
|
||||||
private $delivery_filename;
|
private $delivery_filename;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(ShoppingOrder $model)
|
public function __construct(ShoppingOrder $model)
|
||||||
{
|
{
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
|
|
@ -130,7 +131,7 @@ class InvoiceRepository extends BaseRepository {
|
||||||
if(!Storage::disk('public')->exists( $this->delivery_dir )){
|
if(!Storage::disk('public')->exists( $this->delivery_dir )){
|
||||||
Storage::disk('public')->makeDirectory($this->delivery_dir); //creates directory
|
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 = new InvoicePDF('pdf.invoice');
|
||||||
$pdf_file->create($data, $this->filename, 'save', $path.$this->dir);
|
$pdf_file->create($data, $this->filename, 'save', $path.$this->dir);
|
||||||
|
|
@ -176,6 +177,10 @@ class InvoiceRepository extends BaseRepository {
|
||||||
foreach($whitelabel_image->attributes as $attribute){
|
foreach($whitelabel_image->attributes as $attribute){
|
||||||
if(in_array($attribute, $label->attributes)){
|
if(in_array($attribute, $label->attributes)){
|
||||||
//found and overwrite
|
//found and overwrite
|
||||||
|
if(!$this->model->user_white_label){
|
||||||
|
$this->model->user_white_label = true;
|
||||||
|
$this->model->save();
|
||||||
|
}
|
||||||
$labels[$key] = $whitelabel_image;
|
$labels[$key] = $whitelabel_image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +189,6 @@ class InvoiceRepository extends BaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($labels as $key=>$label){
|
foreach($labels as $key=>$label){
|
||||||
//label hat attribue
|
//label hat attribue
|
||||||
$varinats = [];
|
$varinats = [];
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Mail\MailInvoice;
|
use App\Mail\MailInvoice;
|
||||||
|
use App\Mail\MailLogistic;
|
||||||
use App\Services\Util;
|
use App\Services\Util;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
|
|
@ -118,4 +119,9 @@ class Invoice
|
||||||
}
|
}
|
||||||
Mail::to($billing_email)->bcc($bcc)->send(new MailInvoice($shopping_order));
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class PDFMerger {
|
||||||
* Construct and initialize a new instance
|
* Construct and initialize a new instance
|
||||||
* @param Filesystem $oFilesystem
|
* @param Filesystem $oFilesystem
|
||||||
*/
|
*/
|
||||||
public function __construct(Filesystem $oFilesystem = null){
|
public function __construct($oFilesystem = null){
|
||||||
$this->oFilesystem = $oFilesystem;
|
$this->oFilesystem = $oFilesystem;
|
||||||
$this->oFPDI = new FPDI();
|
$this->oFPDI = new FPDI();
|
||||||
$this->tmpFiles = collect([]);
|
$this->tmpFiles = collect([]);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ namespace App\Services;
|
||||||
|
|
||||||
use App\User;
|
use App\User;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\Setting;
|
|
||||||
use App\Mail\MailCheckout;
|
use App\Mail\MailCheckout;
|
||||||
use App\Models\ProductBuy;
|
use App\Models\ProductBuy;
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
|
|
@ -19,15 +18,16 @@ class Payment
|
||||||
|
|
||||||
public static $txaction_text = [
|
public static $txaction_text = [
|
||||||
'paid' => "bezahlt",
|
'paid' => "bezahlt",
|
||||||
'appointed' => "offen",
|
'open' => "offen",
|
||||||
|
'appointed' => "offen (appointed)",
|
||||||
'failed' => "abbruch",
|
'failed' => "abbruch",
|
||||||
'extern' => "extern",
|
'extern' => "extern",
|
||||||
'open' => "offen",
|
|
||||||
'invoice_open' => "Re. offen",
|
'invoice_open' => "Re. offen",
|
||||||
'invoice_paid' => "Re. bezahlt",
|
'invoice_paid' => "Re. bezahlt",
|
||||||
'invoice_non' => "Re. keine Zahlung",
|
'invoice_non' => "Re. keine Zahlung",
|
||||||
'non' => "keine Zahlung",
|
'non' => "keine Zahlung (non)",
|
||||||
'NULL' => 'keine Zahlung',
|
'NULL' => 'keine Zahlung',
|
||||||
|
'prev' => "keine Zahlung (prev)",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $txaction_invoice = [
|
public static $txaction_invoice = [
|
||||||
|
|
@ -56,10 +56,10 @@ class Payment
|
||||||
'invoice_open' => "warning",
|
'invoice_open' => "warning",
|
||||||
'invoice_paid' => "success",
|
'invoice_paid' => "success",
|
||||||
'invoice_non' => "danger",
|
'invoice_non' => "danger",
|
||||||
|
'prev' => "warning",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public static function getFormattedTxaction($txaction){
|
public static function getFormattedTxaction($txaction){
|
||||||
if($txaction && isset(self::$txaction_text[$txaction])){
|
if($txaction && isset(self::$txaction_text[$txaction])){
|
||||||
return 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){
|
public static function paymentStatusSendMail(ShoppingOrder $shopping_order, $shopping_payment, $data)
|
||||||
$bcc = [];
|
{
|
||||||
$billing_email = $shopping_order->shopping_user->billing_email;
|
$billing_email = self::determineBillingEmail($shopping_order, $data);
|
||||||
if(!$billing_email){
|
$bcc = self::determineBccRecipients($shopping_order, $data);
|
||||||
if($data['mode'] === 'test'){
|
|
||||||
$billing_email = config('app.checkout_test_mail');
|
try {
|
||||||
}else{
|
Mail::to($billing_email)
|
||||||
$billing_email = config('app.checkout_mail');
|
->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{
|
private static function determineBillingEmail($shopping_order, $data)
|
||||||
$bcc[] = config('app.checkout_mail');
|
{
|
||||||
|
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;
|
$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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -30,6 +30,7 @@ class UserBot
|
||||||
|
|
||||||
//user die manuelle Gutschriften haben
|
//user die manuelle Gutschriften haben
|
||||||
$usersWithCreditMargin = $this->getUsersWithCreditMargin();
|
$usersWithCreditMargin = $this->getUsersWithCreditMargin();
|
||||||
|
|
||||||
//user die Shop Provisionen haben
|
//user die Shop Provisionen haben
|
||||||
$usersWithShopCommission = $this->getUsersWithShopCommission(false);
|
$usersWithShopCommission = $this->getUsersWithShopCommission(false);
|
||||||
|
|
||||||
|
|
@ -181,9 +182,9 @@ class UserBot
|
||||||
$entry->badge = \App\Services\Payment::getPaymentForTypeBadge($shoppingOrderMargin->shopping_order);
|
$entry->badge = \App\Services\Payment::getPaymentForTypeBadge($shoppingOrderMargin->shopping_order);
|
||||||
|
|
||||||
if ($shoppingOrderMargin->shopping_order->payment_for === 7 || $shoppingOrderMargin->shopping_order->payment_for === 8) {
|
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 {
|
} 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 . " " .
|
$entry->name = $shoppingOrderMargin->shopping_order->shopping_user->billing_firstname . " " .
|
||||||
|
|
@ -258,7 +259,8 @@ class UserBot
|
||||||
->whereOutPaid(false)
|
->whereOutPaid(false)
|
||||||
->whereCancellation(false)
|
->whereCancellation(false)
|
||||||
->whereMarginPaid(false)
|
->whereMarginPaid(false)
|
||||||
->whereNotNull('margin_pending_to');
|
->whereNotNull('margin_pending_to')
|
||||||
|
->whereIn('status', [7,8]);
|
||||||
|
|
||||||
if ($isPending) {
|
if ($isPending) {
|
||||||
$query->where('margin_pending_to', '>=', Carbon::now());
|
$query->where('margin_pending_to', '>=', Carbon::now());
|
||||||
|
|
|
||||||
13
app/Services/PaymentHelper.php
Normal file
13
app/Services/PaymentHelper.php
Normal 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",
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
453
app/Services/PaymentReminderService.php
Normal file
453
app/Services/PaymentReminderService.php
Normal 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
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
201
app/Services/PaymentService.php
Normal file
201
app/Services/PaymentService.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,11 @@ class UserMarign
|
||||||
return $sum_net_amount;
|
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();
|
$now = $date ? Carbon::parse($date) : Carbon::now();
|
||||||
$startDay = $now->startOfMonth()->toDateString();
|
$startDay = $now->startOfMonth()->toDateString();
|
||||||
|
|
@ -202,7 +206,8 @@ class UserMarign
|
||||||
->whereOutPaid(false)
|
->whereOutPaid(false)
|
||||||
->whereCancellation(false)
|
->whereCancellation(false)
|
||||||
->whereMarginPaid(false)
|
->whereMarginPaid(false)
|
||||||
->whereNotNull('margin_pending_to');
|
->whereNotNull('margin_pending_to')
|
||||||
|
->whereIn('status', [7,8]);
|
||||||
|
|
||||||
if ($isPending) {
|
if ($isPending) {
|
||||||
$query->where('margin_pending_to', '>=', Carbon::now());
|
$query->where('margin_pending_to', '>=', Carbon::now());
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ namespace App\Services;
|
||||||
|
|
||||||
use Yard;
|
use Yard;
|
||||||
use App\User;
|
use App\User;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use App\Models\PromotionUser;
|
use App\Models\PromotionUser;
|
||||||
use App\Models\ShippingCountry;
|
use App\Models\ShippingCountry;
|
||||||
|
|
||||||
|
|
@ -18,7 +19,7 @@ class UserService
|
||||||
public static function createConfirmationCode() {
|
public static function createConfirmationCode() {
|
||||||
$unique = false;
|
$unique = false;
|
||||||
do{
|
do{
|
||||||
$confirmation_code = str_random(30);
|
$confirmation_code = Str::random(30);
|
||||||
if(User::where('confirmation_code', '=', $confirmation_code)->count() == 0){
|
if(User::where('confirmation_code', '=', $confirmation_code)->count() == 0){
|
||||||
$unique = true;
|
$unique = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class Util
|
||||||
|
|
||||||
public static function getToken()
|
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()
|
public static function uuidToken()
|
||||||
|
|
@ -127,7 +127,7 @@ class Util
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setUserHistoryValue($values = [], $identifier){
|
public static function setUserHistoryValue($values, $identifier){
|
||||||
if($user_history = self::getUserHistory($identifier)){
|
if($user_history = self::getUserHistory($identifier)){
|
||||||
foreach ($values as $key=>$val){
|
foreach ($values as $key=>$val){
|
||||||
$user_history->{$key} = $val;
|
$user_history->{$key} = $val;
|
||||||
|
|
@ -171,6 +171,13 @@ class Util
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isTestSystem(){
|
||||||
|
if(config('app.debug')){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static function isPromotionUrl($debug = false){
|
public static function isPromotionUrl($debug = false){
|
||||||
if($debug && config('app.debug')){
|
if($debug && config('app.debug')){
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
110
composer.json
110
composer.json
|
|
@ -8,49 +8,51 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4|^8.0",
|
"php": "^8.2",
|
||||||
"cocur/slugify": "^4.6.0",
|
"alban/laravel-collective-spatie-html-parser": "^1.1.9",
|
||||||
"askedio/laravel5-profanity-filter": "*",
|
"barryvdh/laravel-dompdf": "^2.2",
|
||||||
"barryvdh/laravel-dompdf": "*",
|
"cocur/slugify": "^4.5",
|
||||||
"cviebrock/eloquent-sluggable": "*",
|
"cviebrock/eloquent-sluggable": "^11.0",
|
||||||
"doctrine/dbal": "*",
|
"doctrine/dbal": "^3.6.0|^4.0",
|
||||||
"fideloper/proxy": "^4.4",
|
"guzzlehttp/guzzle": "^7.4",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"intervention/image": "^3",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"jenssegers/date": "^4.0",
|
||||||
"intervention/image": "^2.7",
|
"joedixon/laravel-translation": "2.x-dev",
|
||||||
"jenssegers/date": "*",
|
"laracasts/flash": "^3.2",
|
||||||
"laracasts/flash": "*",
|
"laravel/framework": "^11.0",
|
||||||
"laravel/framework": "^8.12",
|
"laravel/passport": "^12.0",
|
||||||
"laravel/helpers": "*",
|
"laravel/prompts": "^0.1.14",
|
||||||
"laravel/passport": "*",
|
"laravel/tinker": "^2.9",
|
||||||
"laravel/tinker": "^2.5",
|
"laravel/ui": "^4.2",
|
||||||
"laravel/ui": "^3.4",
|
|
||||||
"laravelcollective/html": "*",
|
|
||||||
"maatwebsite/excel": "^3.1",
|
"maatwebsite/excel": "^3.1",
|
||||||
"reliese/laravel": "*",
|
"setasign/fpdf": "^1.8.6",
|
||||||
"rguedes/pdfmerger": "^1.0",
|
"setasign/fpdi": "^2.6",
|
||||||
"setasign/fpdf": "*",
|
"wearepixel/laravel-google-shopping-feed": "^4.0",
|
||||||
"setasign/fpdi": "*",
|
"yajra/laravel-datatables-oracle": "^11.0",
|
||||||
"srmklive/paypal": "~3.0",
|
"srmklive/paypal": "~3.0"
|
||||||
"yajra/laravel-datatables-oracle": "*"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facade/ignition": "^2.5",
|
"spatie/laravel-ignition": "^2.0",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"nunomaduro/collision": "^8.1",
|
||||||
"laravel/sail": "^1.0.1",
|
"fakerphp/faker": "^1.23",
|
||||||
"mockery/mockery": "^1.4.2",
|
"laravel/pint": "^1.0",
|
||||||
"nunomaduro/collision": "^5.0",
|
"laravel/sail": "^1.26",
|
||||||
"phpunit/phpunit": "^9.3.3",
|
"mockery/mockery": "^1.6.2",
|
||||||
"barryvdh/laravel-debugbar": "*",
|
"pestphp/pest": "^2.0",
|
||||||
"barryvdh/laravel-ide-helper": "*"
|
"pestphp/pest-plugin-laravel": "^2.0",
|
||||||
},
|
"barryvdh/laravel-debugbar": "^3.13",
|
||||||
"conflict": {
|
"barryvdh/laravel-ide-helper": "^3.0"
|
||||||
"cocur/slugify": "4.5.0"
|
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
"preferred-install": "dist",
|
"preferred-install": "dist",
|
||||||
"sort-packages": true
|
"sort-packages": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"pestphp/pest-plugin": true,
|
||||||
|
"php-http/discovery": true,
|
||||||
|
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||||
|
"composer/installers": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
|
|
@ -73,25 +75,35 @@
|
||||||
"Tests\\": "tests/"
|
"Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"scripts": {
|
||||||
"prefer-stable": true,
|
|
||||||
"scripts": {
|
|
||||||
"post-update-cmd": [
|
|
||||||
"php artisan clear-compiled",
|
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
|
|
||||||
"php artisan ide-helper:generate",
|
|
||||||
"php artisan ide-helper:meta",
|
|
||||||
"php artisan ide-helper:models"
|
|
||||||
],
|
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
"@php artisan package:discover --ansi"
|
"@php artisan package:discover --ansi",
|
||||||
|
"@php artisan vendor:publish --force --tag=livewire:assets --ansi"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
|
||||||
|
"php artisan ide-helper:generate",
|
||||||
|
"php artisan ide-helper:meta",
|
||||||
|
"php artisan ide-helper:models"
|
||||||
],
|
],
|
||||||
"post-root-package-install": [
|
"post-root-package-install": [
|
||||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
],
|
],
|
||||||
"post-create-project-cmd": [
|
"post-create-project-cmd": [
|
||||||
"@php artisan key:generate --ansi"
|
"@php artisan key:generate --ansi",
|
||||||
|
"@php artisan storage:link --ansi"
|
||||||
|
],
|
||||||
|
"format": [
|
||||||
|
"./vendor/bin/pint"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/bjhijmans/laravel-translation.git"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5560
composer.lock
generated
5560
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,385 +0,0 @@
|
||||||
<?php
|
|
||||||
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;
|
|
||||||
use App\Models\UserPayCredit;
|
|
||||||
use App\Models\ShoppingPayment;
|
|
||||||
use App\Models\UserCreditMargin;
|
|
||||||
use App\Models\PromotionUserOrder;
|
|
||||||
use Illuminate\Support\Facades\Mail;
|
|
||||||
|
|
||||||
class Payment
|
|
||||||
{
|
|
||||||
|
|
||||||
public static $txaction_text = [
|
|
||||||
'paid' => "bezahlt",
|
|
||||||
'appointed' => "offen",
|
|
||||||
'failed' => "abbruch",
|
|
||||||
'extern' => "extern",
|
|
||||||
'open' => "offen",
|
|
||||||
'invoice_open' => "Re. offen",
|
|
||||||
'invoice_paid' => "Re. bezahlt",
|
|
||||||
'invoice_non' => "Re. keine Zahlung",
|
|
||||||
'non' => "keine Zahlung",
|
|
||||||
'NULL' => 'keine Zahlung',
|
|
||||||
];
|
|
||||||
|
|
||||||
public static $txaction_invoice = [
|
|
||||||
'open' => "offen",
|
|
||||||
'paid' => "bezahlt",
|
|
||||||
'non' => "keine Zahlung",
|
|
||||||
/*'open_vor' => "Vorkasse offen",
|
|
||||||
'paid_vor' => "Vorkasse bezahlt",
|
|
||||||
'non_vor' => "Vorkasse keine Zahlung",
|
|
||||||
'invoice_open' => "Rechung offen",
|
|
||||||
'invoice_paid' => "Rechung bezahlt",
|
|
||||||
'invoice_non' => 'Rechung keine Zahlung',*/
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
public static $txaction_color = [
|
|
||||||
'appointed' => "warning",
|
|
||||||
'failed' => "danger",
|
|
||||||
'extern' => "success",
|
|
||||||
'open' => "warning",
|
|
||||||
'paid' => "success",
|
|
||||||
'non' => "danger",
|
|
||||||
'open_vor' => "warning",
|
|
||||||
'paid_vor' => "success",
|
|
||||||
'non_vor' => "danger",
|
|
||||||
'invoice_open' => "warning",
|
|
||||||
'invoice_paid' => "success",
|
|
||||||
'invoice_non' => "danger",
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
public static function getFormattedTxaction($txaction){
|
|
||||||
if($txaction && isset(self::$txaction_text[$txaction])){
|
|
||||||
return self::$txaction_text[$txaction];
|
|
||||||
}
|
|
||||||
return self::$txaction_text['NULL'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getFormattedTxactionColor($txaction){
|
|
||||||
if($txaction && isset(self::$txaction_color[$txaction])){
|
|
||||||
return self::$txaction_color[$txaction];
|
|
||||||
}
|
|
||||||
return "warning";
|
|
||||||
}
|
|
||||||
public static function generateNextInvoiceNumber(){
|
|
||||||
$invoice_number = \App\Models\Setting::getContentBySlug('invoice-number');
|
|
||||||
return $invoice_number;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getShoppingOrderBadge(ShoppingOrder $shopping_order){
|
|
||||||
if($shopping_order->mode === 'test'){
|
|
||||||
return '<span class="badge badge-pill badge-default">'.strtoupper($shopping_order->mode).' - '.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
|
||||||
}
|
|
||||||
if($shopping_order->mode === 'dev'){
|
|
||||||
return '<span class="badge badge-pill badge-info">'.strtoupper($shopping_order->mode).' - '.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
|
||||||
}
|
|
||||||
return '<span class="badge badge-pill badge-'.self::getFormattedTxactionColor($shopping_order->txaction).'">'.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPaymentForTypeBadge(ShoppingOrder $shopping_order){
|
|
||||||
return '<span class="badge badge-pill badge-'.$shopping_order->getPaymentForColor().'">'.$shopping_order->getPaymentForType().'</span>';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getShoppingPaymentBadge(ShoppingPayment $shopping_payment){
|
|
||||||
if($shopping_payment->mode === 'test'){
|
|
||||||
return '<span class="badge badge-pill badge-default">'.strtoupper($shopping_payment->mode).' - '.self::getFormattedTxaction($shopping_payment->txaction).'</span>';
|
|
||||||
}
|
|
||||||
return '<span class="badge badge-pill badge-'.self::getFormattedTxactionColor($shopping_payment->txaction).'">'.self::getFormattedTxaction($shopping_payment->txaction).'</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function addUserPayCredits(User $user, $credit, $status, $message, $shopping_order_id = null){
|
|
||||||
UserPayCredit::create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'credit' => $credit,
|
|
||||||
'old_credit_total' => $user->payment_credit,
|
|
||||||
'new_credit_total' => $user->payment_credit + $credit,
|
|
||||||
'message' => $message,
|
|
||||||
'status' => $status,
|
|
||||||
'shopping_order_id' => $shopping_order_id,
|
|
||||||
]);
|
|
||||||
$user->payment_credit = $user->payment_credit + $credit;
|
|
||||||
$user->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static function addUserCreditMargin(User $user, $credit, $status, $message){
|
|
||||||
UserCreditMargin::create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'credit' => $credit,
|
|
||||||
'message' => $message,
|
|
||||||
'status' => $status,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function addProductBuy(User $user, Product $product){
|
|
||||||
|
|
||||||
if($product->max_buy && $product->max_buy_num > 0){
|
|
||||||
$ProductBuy = ProductBuy::where('auth_user_id', $user->id)->where('product_id', $product->id)->first();
|
|
||||||
if(!$ProductBuy){
|
|
||||||
ProductBuy::create([
|
|
||||||
'auth_user_id' => $user->id,
|
|
||||||
'product_id' => $product->id,
|
|
||||||
'num' => 1,
|
|
||||||
]);
|
|
||||||
}else{
|
|
||||||
$ProductBuy->num = $ProductBuy->num+1;
|
|
||||||
$ProductBuy->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**/
|
|
||||||
public static function paymentStatusPaidAction(ShoppingOrder $shopping_order, $paid){
|
|
||||||
$send_link = false;
|
|
||||||
|
|
||||||
$shopping_order->setUserHistoryValue(['status' => 8]);
|
|
||||||
Shop::userOrders();
|
|
||||||
$shopping_order->paid = $paid;
|
|
||||||
$shopping_order->save();
|
|
||||||
|
|
||||||
//if product has actions
|
|
||||||
if($shopping_order->shopping_order_items && $shopping_order->auth_user_id){
|
|
||||||
foreach($shopping_order->shopping_order_items as $shopping_order_item){
|
|
||||||
if($shopping_order_item->product){
|
|
||||||
//add product when buy
|
|
||||||
$user = User::findOrFail($shopping_order->auth_user_id);
|
|
||||||
|
|
||||||
if($shopping_order_item->product->max_buy && $shopping_order_item->product->max_buy_num > 0){
|
|
||||||
self::addProductBuy($user, $shopping_order_item->product);
|
|
||||||
}
|
|
||||||
//product action
|
|
||||||
if($shopping_order_item->product->action){
|
|
||||||
$user->save();
|
|
||||||
$send_link = true;
|
|
||||||
//new date
|
|
||||||
$date = \Carbon::now()->modify('1 year');
|
|
||||||
if($user->payment_account && $user->daysActiveAccount()>0){
|
|
||||||
$date = \Carbon::parse($user->payment_account)->modify('1 year');
|
|
||||||
}
|
|
||||||
foreach ($shopping_order_item->product->action as $do){
|
|
||||||
if($shopping_order_item->product->getActionName($do) === 'payment_for_account' && !$shopping_order_item->handle){
|
|
||||||
// $user->payment_order_id = $shopping_order_item->product->id; //34
|
|
||||||
$user->payment_account = $date;
|
|
||||||
$user->wizard = 100;
|
|
||||||
$user->save();
|
|
||||||
self::addUserPayCredits($user, $shopping_order_item->product->price, 1, 'payment_for_account', $shopping_order->id);
|
|
||||||
$shopping_order_item->handle = true;
|
|
||||||
$shopping_order_item->save();
|
|
||||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
|
||||||
|
|
||||||
}
|
|
||||||
if($shopping_order_item->product->getActionName($do) === 'charging_credits' && !$shopping_order_item->handle){
|
|
||||||
self::addUserPayCredits($user, ($shopping_order_item->product->price * $shopping_order_item->qty), 7, 'charging_credits_add', $shopping_order->id);
|
|
||||||
$shopping_order_item->handle = true;
|
|
||||||
$shopping_order_item->save();
|
|
||||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if($shopping_order_item->product->getActionName($do) === 'payment_for_shop'){
|
|
||||||
$user->payment_order_id = $shopping_order_item->product->id; //35
|
|
||||||
$user->payment_shop = $date;
|
|
||||||
$user->wizard = 100;
|
|
||||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
|
||||||
}
|
|
||||||
if($shopping_order_item->product->getActionName($do) === 'payment_for_shop_upgrade'){
|
|
||||||
if($shopping_order_item->product->upgrade_to_id){
|
|
||||||
$user->payment_order_id = $shopping_order_item->product->upgrade_to_id;
|
|
||||||
}
|
|
||||||
$user->payment_shop = $user->payment_account; //same Date, is upgrade
|
|
||||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
|
||||||
}
|
|
||||||
if($shopping_order_item->product->getActionName($do) === 'payment_for_lead_upgrade'){
|
|
||||||
if($shopping_order_item->product->upgrade_to_id){
|
|
||||||
$user->m_level = $shopping_order_item->product->upgrade_to_id;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
//$user->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if the order has action
|
|
||||||
if(($shopping_order->shopping_user->is_from === 'user_order' || $shopping_order->shopping_user->is_from === 'shopping') && $shopping_order->shopping_order_margin){
|
|
||||||
//is margin -> set paid
|
|
||||||
$shopping_order->shopping_order_margin->order_paid = true;
|
|
||||||
$shopping_order->shopping_order_margin->save();
|
|
||||||
}
|
|
||||||
return $send_link;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handelPromotionProduct(ShoppingOrder $shopping_order){
|
|
||||||
//add the Promotion Product to Order
|
|
||||||
$shopping_order = ShoppingOrder::find($shopping_order->id);
|
|
||||||
foreach($shopping_order->shopping_order_items as $shopping_order_item){
|
|
||||||
if($shopping_order_item->isFreeProduct()){
|
|
||||||
if($promotion_user_product = $shopping_order_item->promotion_user_product){
|
|
||||||
$promotion_admin_product = $promotion_user_product->promotion_admin_product;
|
|
||||||
$PromotionUserOrder = PromotionUserOrder::create([
|
|
||||||
'promotion_admin_id' => $promotion_user_product->promotion_admin_id,
|
|
||||||
'promotion_user_id' => $shopping_order->promotion_user_id,
|
|
||||||
'promotion_user_product_id' => $promotion_user_product->id,
|
|
||||||
'product_id' => $promotion_user_product->product_id,
|
|
||||||
'shopping_order_item_id' => $shopping_order_item->id,
|
|
||||||
'shopping_order_id' => $shopping_order->id,
|
|
||||||
'shopping_user_id' => $shopping_order->shopping_user_id,
|
|
||||||
'qty' => $shopping_order_item->qty,
|
|
||||||
'price' => $promotion_admin_product->getPriceWith(false),
|
|
||||||
'price_net' => $promotion_admin_product->getPriceWith(true),
|
|
||||||
'tax_rate' => $promotion_admin_product->product->tax,
|
|
||||||
'status' => 0,
|
|
||||||
'pick_up' => $shopping_order->isPickUp()
|
|
||||||
]);
|
|
||||||
|
|
||||||
$promotion_user_product->open_items -= $PromotionUserOrder->qty;
|
|
||||||
$promotion_user_product->sell_items += $PromotionUserOrder->qty;
|
|
||||||
$promotion_user_product->used_budget_total += $PromotionUserOrder->price;
|
|
||||||
$promotion_user_product->save();
|
|
||||||
|
|
||||||
//Guthaben abziehen wenn nicht abholung
|
|
||||||
if(!$shopping_order->isPickUp()){
|
|
||||||
self::addUserPayCredits($promotion_user_product->promotion_user->user, ($PromotionUserOrder->price*-1), 5, 'promotion_order_deduction', $shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove or add form credit, is from Charging credits, handle is true (by paymentStatusPaidAction first action by paid)
|
|
||||||
public static function handelUserPayChargingCredits(ShoppingOrder $shopping_order, $action){
|
|
||||||
//only from cr <- credit Charging
|
|
||||||
if($shopping_order->shopping_user->is_for !== 'cr'){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if($shopping_order->shopping_order_items && $shopping_order->auth_user_id){
|
|
||||||
foreach($shopping_order->shopping_order_items as $shopping_order_item){
|
|
||||||
if($shopping_order_item->product){
|
|
||||||
$user = User::findOrFail($shopping_order->auth_user_id);
|
|
||||||
//product action
|
|
||||||
if($shopping_order_item->product->action){
|
|
||||||
foreach ($shopping_order_item->product->action as $do){
|
|
||||||
if($shopping_order_item->product->getActionName($do) === 'charging_credits' && $shopping_order_item->handle){
|
|
||||||
if($action === 'remove'){
|
|
||||||
self::addUserPayCredits($user, ($shopping_order_item->product->price*-1), 8, 'charging_credits_remove', $shopping_order->id);
|
|
||||||
}
|
|
||||||
if($action === 'add'){
|
|
||||||
self::addUserPayCredits($user, $shopping_order_item->product->price, 7, 'charging_credits_add', $shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove form credit, every sale fnc / vor / etc from CheckoutController
|
|
||||||
//when done, put it back SalesController
|
|
||||||
public static function handelUserPayCredits(ShoppingOrder $shopping_order, $do){
|
|
||||||
//is payment credit, deduction or return
|
|
||||||
if(!$shopping_order->shopping_order_margin){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if($do === 'deduction'){
|
|
||||||
if($shopping_order->shopping_order_margin->from_payment_credit > 0){
|
|
||||||
$credit = $shopping_order->shopping_order_margin->from_payment_credit * -1;
|
|
||||||
self::addUserPayCredits($shopping_order->auth_user, $credit, 2, 'user_order_deduction', $shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($do === 'return'){
|
|
||||||
if($shopping_order->shopping_order_margin->from_payment_credit > 0){
|
|
||||||
$credit = $shopping_order->shopping_order_margin->from_payment_credit;
|
|
||||||
self::addUserPayCredits($shopping_order->auth_user, $credit, 4, 'user_order_return', $shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handelUserPromotionOrder(ShoppingOrder $shopping_order){
|
|
||||||
//no user promotion
|
|
||||||
if($shopping_order->payment_for !== 7 || !$shopping_order->promotion_user){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if($shopping_order->promotion_user->promotion_user_orders){
|
|
||||||
foreach($shopping_order->promotion_user->getPromotionUserOrders($shopping_order->id) as $promotion_user_order){
|
|
||||||
$promotion_user_order->setStatusShipped($shopping_order->getAPIShippedType());
|
|
||||||
if(!$promotion_user_order->pick_up){ // keine abholung handel credit
|
|
||||||
$last_UserPayCredit = UserPayCredit::where('shopping_order_id', $shopping_order->id)->whereIn('status', [5, 6])->orderBy('id', 'DESC')->first();
|
|
||||||
if($last_UserPayCredit && $promotion_user_order->status === 10 && $last_UserPayCredit->status === 5){
|
|
||||||
Payment::handelUserPayCreditsPromotion($promotion_user_order, 'return');
|
|
||||||
}
|
|
||||||
//Status Zahlung, voher gab es eine Storno, Guthaben abziehen wenn status 6 / return from order
|
|
||||||
if($last_UserPayCredit && $promotion_user_order->status === 0 && $last_UserPayCredit->status === 6){
|
|
||||||
Payment::handelUserPayCreditsPromotion($promotion_user_order, 'deduction');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function handelUserShopOrder(ShoppingOrder $shopping_order){
|
|
||||||
//no user shop
|
|
||||||
if($shopping_order->payment_for !== 8 || !$shopping_order->user_shop){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// need something to do?
|
|
||||||
}
|
|
||||||
|
|
||||||
//add or remove form credit,
|
|
||||||
//when done, put it back SalesController
|
|
||||||
public static function handelUserPayCreditsPromotion(PromotionUserOrder $promotion_user_order, $do){
|
|
||||||
//is promotion pick up, dont
|
|
||||||
if($promotion_user_order->pick_up){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if($do === 'deduction'){
|
|
||||||
if($promotion_user_order->price > 0){
|
|
||||||
$credit = $promotion_user_order->price * -1;
|
|
||||||
self::addUserPayCredits($promotion_user_order->promotion_user->user, $credit, 5, 'promotion_order_deduction', $promotion_user_order->shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($do === 'return'){
|
|
||||||
if($promotion_user_order->price > 0){
|
|
||||||
$credit = $promotion_user_order->price;
|
|
||||||
self::addUserPayCredits($promotion_user_order->promotion_user->user, $credit, 6, 'promotion_order_return', $promotion_user_order->shopping_order->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($data['mode'] === 'test'){
|
|
||||||
$bcc[] = config('app.checkout_test_mail');
|
|
||||||
}else{
|
|
||||||
$bcc[] = config('app.checkout_mail');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$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']));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -75,6 +75,7 @@ return [
|
||||||
'main_user_id' => env('APP_MAIN_USER_ID', 1),
|
'main_user_id' => env('APP_MAIN_USER_ID', 1),
|
||||||
|
|
||||||
'exception_mail' => env('EXCEPTION_MAIL', 'exception@adametz.media'),
|
'exception_mail' => env('EXCEPTION_MAIL', 'exception@adametz.media'),
|
||||||
|
'logistic_mail' => env('LOGISTIC_MAIL', 'kevin.adametz@me.com'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
@ -185,7 +186,9 @@ return [
|
||||||
/*
|
/*
|
||||||
* Package Service Providers...
|
* Package Service Providers...
|
||||||
*/
|
*/
|
||||||
|
Laravel\Tinker\TinkerServiceProvider::class,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application Service Providers...
|
* Application Service Providers...
|
||||||
*/
|
*/
|
||||||
|
|
@ -194,14 +197,11 @@ return [
|
||||||
// App\Providers\BroadcastServiceProvider::class,
|
// App\Providers\BroadcastServiceProvider::class,
|
||||||
App\Providers\EventServiceProvider::class,
|
App\Providers\EventServiceProvider::class,
|
||||||
App\Providers\RouteServiceProvider::class,
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
|
||||||
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
|
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
|
||||||
Jenssegers\Date\DateServiceProvider::class,
|
Jenssegers\Date\DateServiceProvider::class,
|
||||||
Collective\Html\HtmlServiceProvider::class,
|
Maatwebsite\Excel\ExcelServiceProvider::class,
|
||||||
Intervention\Image\ImageServiceProvider::class,
|
|
||||||
// Maatwebsite\Excel\ExcelServiceProvider::class,
|
|
||||||
Yajra\DataTables\DataTablesServiceProvider::class,
|
Yajra\DataTables\DataTablesServiceProvider::class,
|
||||||
App\Providers\YardServiceProvider::class
|
App\Providers\YardServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
@ -253,7 +253,6 @@ return [
|
||||||
'URL' => Illuminate\Support\Facades\URL::class,
|
'URL' => Illuminate\Support\Facades\URL::class,
|
||||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||||
'View' => Illuminate\Support\Facades\View::class,
|
'View' => Illuminate\Support\Facades\View::class,
|
||||||
'Input' => Illuminate\Support\Facades\Input::class,
|
|
||||||
'Form' => Collective\Html\FormFacade::class,
|
'Form' => Collective\Html\FormFacade::class,
|
||||||
'HTML' => Collective\Html\HtmlFacade::class,
|
'HTML' => Collective\Html\HtmlFacade::class,
|
||||||
'Image' => Intervention\Image\Facades\Image::class,
|
'Image' => Intervention\Image\Facades\Image::class,
|
||||||
|
|
@ -261,7 +260,7 @@ return [
|
||||||
'Date' => Jenssegers\Date\Date::class,
|
'Date' => Jenssegers\Date\Date::class,
|
||||||
'HTMLHelper' => App\Services\HTMLHelper::class,
|
'HTMLHelper' => App\Services\HTMLHelper::class,
|
||||||
'Util' => App\Services\Util::class,
|
'Util' => App\Services\Util::class,
|
||||||
//'Excel' => Maatwebsite\Excel\Facades\Excel::class,
|
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
|
||||||
'DataTables' => Yajra\DataTables\Facades\DataTables::class,
|
'DataTables' => Yajra\DataTables\Facades\DataTables::class,
|
||||||
'Yard' => App\Services\Facade\Yard::class,
|
'Yard' => App\Services\Facade\Yard::class,
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,86 @@ return [
|
||||||
],
|
],
|
||||||
|
|
||||||
/* Replace these words no matter what language. */
|
/* Replace these words no matter what language. */
|
||||||
'defaults' => [
|
'full_word_check' => [
|
||||||
|
'aloe',
|
||||||
|
'aloevera',
|
||||||
|
'mivita',
|
||||||
|
'shop',
|
||||||
|
'onlineshop',
|
||||||
|
'aloeveramallorca',
|
||||||
|
'aloemallorca',
|
||||||
|
'aloeverademallorca',
|
||||||
|
'babydaloe',
|
||||||
'fuck',
|
'fuck',
|
||||||
'shit',
|
'shit',
|
||||||
|
'anal',
|
||||||
|
'anus',
|
||||||
|
'arse',
|
||||||
|
'ass',
|
||||||
|
'ballsack',
|
||||||
|
'balls',
|
||||||
|
'bastard',
|
||||||
|
'bitch',
|
||||||
|
'biatch',
|
||||||
|
'bloody',
|
||||||
|
'blowjob',
|
||||||
|
'bollock',
|
||||||
|
'bollok',
|
||||||
|
'boner',
|
||||||
|
'boob',
|
||||||
|
'bugger',
|
||||||
|
'bum',
|
||||||
|
'butt',
|
||||||
|
'buttplug',
|
||||||
|
'clitoris',
|
||||||
|
'cock',
|
||||||
|
'coon',
|
||||||
|
'crap',
|
||||||
|
'cunt',
|
||||||
|
'damn',
|
||||||
|
'dick',
|
||||||
|
'dildo',
|
||||||
|
'dyke',
|
||||||
|
'fag',
|
||||||
|
'feck',
|
||||||
|
'fellate',
|
||||||
|
'fellatio',
|
||||||
|
'felching',
|
||||||
|
'fuck',
|
||||||
|
'fudgepacker',
|
||||||
|
'flange',
|
||||||
|
'goddamn',
|
||||||
|
'hell',
|
||||||
|
'homo',
|
||||||
|
'jizz',
|
||||||
|
'knobend',
|
||||||
|
'labia',
|
||||||
|
'muff',
|
||||||
|
'nigger',
|
||||||
|
'nigga',
|
||||||
|
'penis',
|
||||||
|
'piss',
|
||||||
|
'poop',
|
||||||
|
'prick',
|
||||||
|
'pube',
|
||||||
|
'pussy',
|
||||||
|
'queer',
|
||||||
|
'scrotum',
|
||||||
|
'sex',
|
||||||
|
'shit',
|
||||||
|
'sh1t',
|
||||||
|
'slut',
|
||||||
|
'smegma',
|
||||||
|
'spunk',
|
||||||
|
'suck',
|
||||||
|
'tit',
|
||||||
|
'tosser',
|
||||||
|
'turd',
|
||||||
|
'twat',
|
||||||
|
'vagina',
|
||||||
|
'wank',
|
||||||
|
'whore',
|
||||||
|
'wtf',
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
1
cron.log
1
cron.log
|
|
@ -1 +0,0 @@
|
||||||
RUN Command Payments Account: 14.12.2022 13:19
|
|
||||||
|
|
@ -48,11 +48,11 @@ class CreateShoppingOrdersTable extends Migration
|
||||||
$table->unsignedInteger('weight')->nullable();
|
$table->unsignedInteger('weight')->nullable();
|
||||||
|
|
||||||
$table->boolean('paid')->default(false);
|
$table->boolean('paid')->default(false);
|
||||||
|
|
||||||
$table->string('invoice_number', 255)->nullable();
|
$table->string('invoice_number', 255)->nullable();
|
||||||
$table->text('invoice')->nullable();
|
$table->text('invoice')->nullable();
|
||||||
$table->text('delivery')->nullable();
|
$table->text('delivery')->nullable();
|
||||||
|
$table->boolean('user_white_label')->default(false);
|
||||||
|
|
||||||
$table->string('wp_invoice_path', 255)->nullable();
|
$table->string('wp_invoice_path', 255)->nullable();
|
||||||
$table->text('wp_notice')->nullable();
|
$table->text('wp_notice')->nullable();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ class CreateShoppingPaymentsTable extends Migration
|
||||||
$table->string('status', 10)->nullable()->index();
|
$table->string('status', 10)->nullable()->index();
|
||||||
$table->string('txaction', 20)->nullable()->index();
|
$table->string('txaction', 20)->nullable()->index();
|
||||||
|
|
||||||
|
$table->unsignedSmallInteger('reminder')->nullable();
|
||||||
|
$table->dateTime('reminder_date')->nullable();
|
||||||
|
|
||||||
$table->char('mode', 4)->nullable();
|
$table->char('mode', 4)->nullable();
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('payment_reminders', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
|
||||||
|
$table->string('title')->nullable();
|
||||||
|
$table->string('subject')->nullable();
|
||||||
|
$table->unsignedSmallInteger('interval')->nullable();
|
||||||
|
$table->text('message')->nullable();
|
||||||
|
$table->string('action')->nullable();
|
||||||
|
$table->string('clearingtype', 3)->nullable();
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('payment_reminders');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,102 +1,106 @@
|
||||||
body {
|
body {
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
}
|
}
|
||||||
.text-muted {
|
.text-muted {
|
||||||
color: #8e8f90 !important;
|
color: #8e8f90 !important;
|
||||||
}
|
}
|
||||||
.btn-primary:hover {
|
.btn-primary:hover {
|
||||||
background: #5f7567;
|
background: #5f7567;
|
||||||
}
|
}
|
||||||
.btn-primary:focus,
|
.btn-primary:focus,
|
||||||
.btn-primary.focus {
|
.btn-primary.focus {
|
||||||
background: #5f7567;
|
background: #5f7567;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #46564d;
|
color: #46564d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #5f7567;
|
color: #5f7567;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-success {
|
.alert-success {
|
||||||
border-color: #f2ffeb;
|
border-color: #f2ffeb;
|
||||||
background-color: #b5c49b;
|
background-color: #b5c49b;
|
||||||
color: #f2ffea;
|
color: #f2ffea;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr-lg-1-5 {
|
.mr-lg-1-5 {
|
||||||
margin-right: 1rem !important;
|
margin-right: 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#accordion a.card-header {
|
#accordion a.card-header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0.6rem 1.5rem;
|
padding: 0.6rem 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#accordion a.card-header:hover, #accordion a.card-header:focus {
|
#accordion a.card-header:hover,
|
||||||
background: #fff;
|
#accordion a.card-header:focus {
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-dark[href]:hover {
|
.text-dark[href]:hover {
|
||||||
color: #696f5b !important
|
color: #696f5b !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#accordion .card-body {
|
#accordion .card-body {
|
||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
}
|
}
|
||||||
.user-view-table tr td:first-child {
|
.user-view-table tr td:first-child {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table th, .table td {
|
.table th,
|
||||||
border-top: 1px solid #d6d6de;
|
.table td {
|
||||||
|
border-top: 1px solid #d6d6de;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer.bg-white .footer-link:hover, .footer.bg-white .footer-link:focus {
|
.footer.bg-white .footer-link:hover,
|
||||||
color: rgba(0, 0, 0, 0.9);
|
.footer.bg-white .footer-link:focus {
|
||||||
text-decoration: underline;
|
color: rgba(0, 0, 0, 0.9);
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.footer.bg-white .footer-link {
|
.footer.bg-white .footer-link {
|
||||||
color: rgba(0, 0, 0, 1);
|
color: rgba(0, 0, 0, 1);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
.footer p {
|
.footer p {
|
||||||
color:#000;
|
color: #000;
|
||||||
}
|
}
|
||||||
.footer.bg-white {
|
.footer.bg-white {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
}
|
}
|
||||||
.footer a {
|
.footer a {
|
||||||
color:#000;
|
color: #000;
|
||||||
|
|
||||||
}
|
}
|
||||||
.footer a:hover {
|
.footer a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge-success {
|
.badge-success {
|
||||||
background-color: #b5c49b;
|
background-color: #b5c49b;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control.has-error {
|
.form-control.has-error {
|
||||||
border: 1px solid #ea8e49;
|
border: 1px solid #ea8e49;
|
||||||
}
|
}
|
||||||
.text-dark.active {
|
.text-dark.active {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
background-color: #928876 !important;
|
background-color: #928876 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-toggle="collapse"].collapsed .if-not-collapsed {
|
[data-toggle="collapse"].collapsed .if-not-collapsed {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
|
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-warning-dark {
|
||||||
|
background-color: #f98000;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,5 +200,8 @@
|
||||||
"open your shop": "Er\u00f6ffne Deinen eigenen Shop",
|
"open your shop": "Er\u00f6ffne Deinen eigenen Shop",
|
||||||
"settings your shop": "Deine Shop-Einstellungen",
|
"settings your shop": "Deine Shop-Einstellungen",
|
||||||
"taxable_sales_1": "umsatzsteuerpflichtig (Ich mache eine UST-Voranmeldung pro Monat \/ Quartal \/ Jahr ans Finanzamt)",
|
"taxable_sales_1": "umsatzsteuerpflichtig (Ich mache eine UST-Voranmeldung pro Monat \/ Quartal \/ Jahr ans Finanzamt)",
|
||||||
"taxable_sales_2": "nicht umsatzsteuerpflichtig (Kleinunternehmer im Sinne von \u00a7 19)"
|
"taxable_sales_2": "nicht umsatzsteuerpflichtig (Kleinunternehmer im Sinne von \u00a7 19)",
|
||||||
|
"Order": "Bestellung",
|
||||||
|
"Orders": "Bestellungen"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -92,4 +92,5 @@
|
||||||
'checkout_mail_pay_invoice_open' => 'Deine Zahlung per Rechnung wurde genehmigt.',
|
'checkout_mail_pay_invoice_open' => 'Deine Zahlung per Rechnung wurde genehmigt.',
|
||||||
'checkout_mail_pay_non' => 'Deine Bestellung wurde ausgeführt.',
|
'checkout_mail_pay_non' => 'Deine Bestellung wurde ausgeführt.',
|
||||||
'checkout_mail_system_status' => 'SystemStatus:',
|
'checkout_mail_system_status' => 'SystemStatus:',
|
||||||
|
'my_orders' => 'Meine Bestellungen',
|
||||||
);
|
);
|
||||||
|
|
@ -43,6 +43,7 @@ return [
|
||||||
'payments' => 'Zahlungen',
|
'payments' => 'Zahlungen',
|
||||||
'credit' => 'Gutschriften',
|
'credit' => 'Gutschriften',
|
||||||
'invoice' => 'Rechnungen',
|
'invoice' => 'Rechnungen',
|
||||||
|
'reminder' => 'Erinnerungen',
|
||||||
'revenue' => 'Umsätze',
|
'revenue' => 'Umsätze',
|
||||||
'paycredit' => 'Einkaufsguthaben',
|
'paycredit' => 'Einkaufsguthaben',
|
||||||
'commissions' => 'Provisionen',
|
'commissions' => 'Provisionen',
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@
|
||||||
|
|
||||||
@if(Yard::instance('shopping')->content()->count())
|
@if(Yard::instance('shopping')->content()->count())
|
||||||
<!-- CART -->
|
<!-- CART -->
|
||||||
{!! Form::open(['url' => url(Util::getPostRoute().'card/update'), 'class' => 'cartContent clearfix', 'id'=>'']) !!}
|
{!! Form::open(['action' => url(Util::getPostRoute().'card/update'), 'class' => 'cartContent clearfix', 'id'=>'']) !!}
|
||||||
|
|
||||||
<!-- cart content -->
|
<!-- cart content -->
|
||||||
<div id="cartContent">
|
<div id="cartContent">
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
|
|
||||||
<div class="m-checkout">
|
<div class="m-checkout">
|
||||||
|
|
||||||
{!! Form::open(['url' => route('checkout.checkout_card_final'), 'class' => 'row clearfix', 'id'=>'checkout_card_final']) !!}
|
{!! Form::open(['action' => route('checkout.checkout_card_final'), 'class' => 'row clearfix', 'id'=>'checkout_card_final']) !!}
|
||||||
|
|
||||||
{!! Form::hidden('selected_country', '') !!}
|
{!! Form::hidden('selected_country', '') !!}
|
||||||
{!! Form::hidden('is_for', $shopping_user->is_for) !!}
|
{!! Form::hidden('is_for', $shopping_user->is_for) !!}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@
|
||||||
<p>Du interessierst Dich für unser Geschäft oder hast Fragen zu den Produkten? Dann freuen wir uns auf eine Nachricht von Dir. Wir werden uns im Anschluss sobald wie möglich bei Dir zurückmelden.</p>
|
<p>Du interessierst Dich für unser Geschäft oder hast Fragen zu den Produkten? Dann freuen wir uns auf eine Nachricht von Dir. Wir werden uns im Anschluss sobald wie möglich bei Dir zurückmelden.</p>
|
||||||
|
|
||||||
<div class="box-static box-transparent box-bordered padding-20">
|
<div class="box-static box-transparent box-bordered padding-20">
|
||||||
{!! Form::open(['url' => '/kontakt']) !!}
|
{!! Form::open(['action' => '/kontakt']) !!}
|
||||||
<div class="text-right" style="margin-bottom: 8px; margin-top: -16px;">
|
<div class="text-right" style="margin-bottom: 8px; margin-top: -16px;">
|
||||||
<em class="small">* {{trans('register.required_fields')}}</em>
|
<em class="small">* {{trans('register.required_fields')}}</em>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="shop-item-price text-right" style="line-height: 1.3em">
|
<div class="shop-item-price text-right" style="line-height: 1.3em">
|
||||||
{!! Form::open(['url' => url(Util::getPostRoute().'card/add/'.$product->id), 'class' => 'mb-0', 'id'=>'']) !!}
|
{!! Form::open(['action' => url(Util::getPostRoute().'card/add/'.$product->id), 'class' => 'mb-0', 'id'=>'']) !!}
|
||||||
<div class="qty float-left">
|
<div class="qty float-left">
|
||||||
<input type="number" value="1" name="quantity" maxlength="3" max="999" min="1"><br>
|
<input type="number" value="1" name="quantity" maxlength="3" max="999" min="1"><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
<div class="box-static box-transparent box-bordered padding-20">
|
<div class="box-static box-transparent box-bordered padding-20">
|
||||||
|
|
||||||
{!! Form::open(['url' => '/registrierung']) !!}
|
{!! Form::open(['action' => '/registrierung']) !!}
|
||||||
@if(isset($from_member_id))
|
@if(isset($from_member_id))
|
||||||
{!! Form::hidden('from_member_id', $from_member_id) !!}
|
{!! Form::hidden('from_member_id', $from_member_id) !!}
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
{{ __('Create/Edit Kategorien') }}
|
{{ __('Create/Edit Kategorien') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_product_category_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
{!! Form::open(['action' => route('admin_product_category_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
|
|
||||||
<input type="hidden" name="id" id="id" value="@if($category->id>0){{$category->id}}@else new @endif">
|
<input type="hidden" name="id" id="id" value="@if($category->id>0){{$category->id}}@else new @endif">
|
||||||
<input type="hidden" name="action" value="save-form">
|
<input type="hidden" name="action" value="save-form">
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_lead_change_mail', [$user->id]) ]) !!}
|
{!! Form::open(['action' => route('admin_lead_change_mail', [$user->id]) ]) !!}
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-form-label col-sm-2 text-sm-right">{{__('New E-Mail Address')}}*</label>
|
<label class="col-form-label col-sm-2 text-sm-right">{{__('New E-Mail Address')}}*</label>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
{{ __('Create/Edit Land') }}
|
{{ __('Create/Edit Land') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_country_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
{!! Form::open(['action' => route('admin_country_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
|
|
||||||
<input type="hidden" name="id" id="id" value="@if($country->id>0){{$country->id}}@else new @endif">
|
<input type="hidden" name="id" id="id" value="@if($country->id>0){{$country->id}}@else new @endif">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<a href="{{route('admin_customer_detail', [$shopping_user->id])}}" class="btn btn-sm btn-default float-right">zurück</a>
|
<a href="{{route('admin_customer_detail', [$shopping_user->id])}}" class="btn btn-sm btn-default float-right">zurück</a>
|
||||||
{{ __('Kunden Details') }} bearbeiten
|
{{ __('Kunden Details') }} bearbeiten
|
||||||
</h4>
|
</h4>
|
||||||
{!! Form::open(['url' => route('admin_customer_edit', [$shopping_user->id]), 'class' => 'form-horizontal', 'id'=>'lead-form-validation']) !!}
|
{!! Form::open(['action' => route('admin_customer_edit', [$shopping_user->id]), 'class' => 'form-horizontal', 'id'=>'lead-form-validation']) !!}
|
||||||
@include('admin.customer._edit')
|
@include('admin.customer._edit')
|
||||||
<div class="text-left mt-3">
|
<div class="text-left mt-3">
|
||||||
<button type="submit" class="btn btn-secondary" name="action" value="shopping-user-store">{{ __('save changes') }}</button>
|
<button type="submit" class="btn btn-secondary" name="action" value="shopping-user-store">{{ __('save changes') }}</button>
|
||||||
|
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
@extends('layouts.layout-2')
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
|
|
||||||
@if ($errors->any())
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<ul>
|
|
||||||
@foreach ($errors->all() as $error)
|
|
||||||
<li>{{ $error }}</li>
|
|
||||||
@endforeach
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<h5 class="card-header">
|
|
||||||
{{ __('navigation.products') }} {{ __('navigation.sales_volumes') }}
|
|
||||||
</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
{!! Form::open(['url' => route('admin_evaluation_sales_volumes_download'), 'class' => '']) !!}
|
|
||||||
{!! Form::hidden('key', 'value') !!}
|
|
||||||
<button type="submit" name="action" value="export" class="btn btn-md btn-primary mb-2"><i class="ion ion-md-download"></i> Export als xls</button>
|
|
||||||
<hr>
|
|
||||||
<div class="form-row align-items-center px-0 pb-2 pt-0">
|
|
||||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
|
||||||
<select class="custom-select on_change_select_filter" name="product_sales_vol_filter_month">
|
|
||||||
@foreach($filter_months as $key=>$value)
|
|
||||||
<option value="{{$key}}" @if(session('product_sales_vol_filter_month') == $key) selected @endif>{{$value}}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-6 col-sm-4 col-md-4 col-lg-4 mb-1">
|
|
||||||
<select class="custom-select on_change_select_filter" name="product_sales_vol_filter_year">
|
|
||||||
@foreach($filter_years as $key=>$value)
|
|
||||||
<option value="{{$value}}" @if(session('product_sales_vol_filter_year') == $value) selected @endif>{{$value}}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{!! Form::close() !!}
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-datatable table-responsive">
|
|
||||||
<table class="table table-striped table-bordered" id="datatable-sales-volume">
|
|
||||||
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{{__('#') }}</th>
|
|
||||||
<th>{{__('tables.product')}}</th>
|
|
||||||
<th>{{__('tables.article_no')}}</th>
|
|
||||||
<th>{{__('tables.quantity')}}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
$( document ).ready(function() {
|
|
||||||
|
|
||||||
|
|
||||||
var oTable = $('#datatable-sales-volume').DataTable({
|
|
||||||
"processing": true,
|
|
||||||
"serverSide": true,
|
|
||||||
"stateSave": true,
|
|
||||||
"searching": false,
|
|
||||||
ajax: {
|
|
||||||
url: '{!! route('admin_evaluation_sales_volumes_datatable') !!}',
|
|
||||||
data: function(d) {
|
|
||||||
d.product_sales_vol_filter_month = $('select[name=product_sales_vol_filter_month]').val();
|
|
||||||
d.product_sales_vol_filter_year = $('select[name=product_sales_vol_filter_year]').val();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"order": [[0, "asc" ]],
|
|
||||||
"columns": [
|
|
||||||
{ data: 'id', orderable: true, searchable: false },
|
|
||||||
{ data: 'name', name: 'name', orderable: true, searchable: false },
|
|
||||||
{ data: 'number', name: 'number', orderable: true, searchable: false },
|
|
||||||
{ data: 'value', name: 'value', orderable: true, searchable: false },
|
|
||||||
|
|
||||||
],
|
|
||||||
"bLengthChange": false,
|
|
||||||
"iDisplayLength": 100,
|
|
||||||
"language": {
|
|
||||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('select.on_change_select_filter').on('change', function(){
|
|
||||||
oTable.draw();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('input.on_keyup_input_filter').on('keyup', function(){
|
|
||||||
oTable.draw();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endsection
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
{{ __('Create/Edit Inhaltsstoff') }}
|
{{ __('Create/Edit Inhaltsstoff') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_product_ingredient_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
{!! Form::open(['action' => route('admin_product_ingredient_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
|
|
||||||
<input type="hidden" name="id" id="id" value="@if($model->id>0){{$model->id}}@else new @endif">
|
<input type="hidden" name="id" id="id" value="@if($model->id>0){{$model->id}}@else new @endif">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
@endif
|
@endif
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_lead_store')."?show=".$show, 'class' => 'form-horizontal', 'id'=>'lead-form-validation']) !!}
|
{!! Form::open(['action' => route('admin_lead_store')."?show=".$show, 'class' => 'form-horizontal', 'id'=>'lead-form-validation']) !!}
|
||||||
|
|
||||||
<div class="text-left mt-0 mb-2">
|
<div class="text-left mt-0 mb-2">
|
||||||
<button type="submit" class="btn btn-submit btn-primary">{{ __('save') }}</button>
|
<button type="submit" class="btn btn-submit btn-primary">{{ __('save') }}</button>
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
<!-- Modal template -->
|
<!-- Modal template -->
|
||||||
<div class="modal fade" id="modal-user-vat-validation">
|
<div class="modal fade" id="modal-user-vat-validation">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
{!! Form::open(['url' => route('admin_lead_store'), 'class' => 'modal-content']) !!}
|
{!! Form::open(['action' => route('admin_lead_store'), 'class' => 'modal-content']) !!}
|
||||||
<input type="hidden" name="user_id" id="user_id" value="@if($user->id>0){{$user->id}}@else new @endif">
|
<input type="hidden" name="user_id" id="user_id" value="@if($user->id>0){{$user->id}}@else new @endif">
|
||||||
|
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
{!! Form::open(['url' => route('admin_lead_download'), 'class' => '']) !!}
|
{!! Form::open(['action' => route('admin_lead_download'), 'class' => '']) !!}
|
||||||
<div class="form-row align-items-center">
|
<div class="form-row align-items-center">
|
||||||
<div class="col-sm-5 col-md-5">
|
<div class="col-sm-5 col-md-5">
|
||||||
<label class="form-label" for="filter_user_shop_id">Art Vertriebspartner</label>
|
<label class="form-label" for="filter_user_shop_id">Art Vertriebspartner</label>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
</div>
|
</div>
|
||||||
</h5>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{!! Form::open(['url' => route('admin_lead_update')."?show=".$show, 'class' => 'form-horizontal', 'id'=>'white-label-form']) !!}
|
{!! Form::open(['action' => route('admin_lead_update')."?show=".$show, 'class' => 'form-horizontal', 'id'=>'white-label-form']) !!}
|
||||||
<input type="hidden" name="user_id" value="{{$user->id}}">
|
<input type="hidden" name="user_id" value="{{$user->id}}">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
@if($m_data_error)
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<ul>
|
|
||||||
<li>{{ $m_data_error }}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<div class="card-body m-0 p-0">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table card-table m-0">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 33%">{{ __('Name') }}</th>
|
|
||||||
<th style="width: 66%">{{ __('Account ID') }}</th>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{ \App\Services\HTMLHelper::getSalutationLang($user->account->m_salutation) }} {{ $user->account->m_first_name }} {{ $user->account->m_last_name }}</td>
|
|
||||||
<td>{{ $user->account->m_account }}</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="table card-table m-0">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th style="width: 33%">{{ __('Art Vertriebspartner') }}</th>
|
|
||||||
<th style="width: 33%">{{ __('Rolle') }}</th>
|
|
||||||
<th style="width: 33%">{{ __('Sponsor') }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>@if($user->lead_type) {{ $user->lead_type->name }} @else Standard @endif</td>
|
|
||||||
<td>@if($user->user_level){{ $user->user_level->name }}@endif</td>
|
|
||||||
<td>@if($user->m_sponsor){{ $user->getMUserSponsor() }}@endif</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
@if($user->account->m_notes)
|
|
||||||
<table class="table card-table m-0">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th>{{ __('weitere Daten') }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{$user->account->m_notes}}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mb-2">
|
<div class="card mb-2">
|
||||||
{!! Form::open(['url' => route('admin_level_store',), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
{!! Form::open(['action' => route('admin_level_store',), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
<input type="hidden" name="id" value="@if($value->id>0){{$value->id}}@else new @endif">
|
<input type="hidden" name="id" value="@if($value->id>0){{$value->id}}@else new @endif">
|
||||||
<h5 class="card-header">
|
<h5 class="card-header">
|
||||||
{{ __('Rolle') }}
|
{{ __('Rolle') }}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => route('admin_payments_credit'), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => route('admin_payments_credit'), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">
|
<h5 class="modal-title">
|
||||||
{{ __('Gutschrift') }}
|
{{ __('Gutschrift') }}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => route('admin_payments_paycredit'), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => route('admin_payments_paycredit'), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">
|
<h5 class="modal-title">
|
||||||
{{ __('Einkaufsguthaben') }}
|
{{ __('Einkaufsguthaben') }}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => route('admin_sales_customers_detail', [$current->id]), 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => route('admin_sales_detail', [$current->id]), 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
||||||
|
|
||||||
<input type="hidden" name="action" value="{{$data['action']}}">
|
<input type="hidden" name="action" value="{{$data['action']}}">
|
||||||
<input type="hidden" name="id" value="{{$data['id']}}">
|
<input type="hidden" name="id" value="{{$data['id']}}">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => $route, 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => $route, 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">
|
<h5 class="modal-title">
|
||||||
{{ __('Vertriebspartner') }}
|
{{ __('Vertriebspartner') }}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => route('admin_promotion_detail', [$data['promotion_id']]), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => route('admin_promotion_detail', [$data['promotion_id']]), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">
|
<h5 class="modal-title">
|
||||||
{{ __('Produkt') }} <span class="font-weight-light">hinzufügen / bearbeiten</span>
|
{{ __('Produkt') }} <span class="font-weight-light">hinzufügen / bearbeiten</span>
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
{!! Form::open(['url' => route('admin_payments_credit'), 'class' => 'modal-content form-prevent-multiple-submits', 'enctype' => 'multipart/form-data']) !!}
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">
|
|
||||||
{{ __('Gutschrift') }}
|
|
||||||
<span class="font-weight-light">hinzufügen</span>
|
|
||||||
</h5>
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<input type="hidden" name="action" value="{{$data['action']}}">
|
|
||||||
<input type="hidden" name="id" value="{{$data['id']}}">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-row">
|
|
||||||
<div class="form-group col-12">
|
|
||||||
<label for="member_id" class="form-label">{{ __('Vertriebspartner auswählen') }}*</label>
|
|
||||||
<select class="selectpicker" name="member_id" data-style="btn-light" data-live-search="true" required>
|
|
||||||
{!! HTMLHelper::getMembersOptions(0, true) !!}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group col-12">
|
|
||||||
<label class="form-label" for="credit">{{ __('Betrag') }} netto*</label>
|
|
||||||
{{ Form::text('credit', '', array('placeholder'=>__('in Euro'), 'class'=>'form-control', 'required'=>true)) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group col-12">
|
|
||||||
<label class="form-label" for="message">{{ __('Mitteilung') }}*</label>
|
|
||||||
{{ Form::textarea('message', '' , array('placeholder'=>__('Mitteilung'), 'class'=>'form-control', 'rows'=>4, 'required'=>true)) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">schließen</button>
|
|
||||||
<button type="submit" class="btn btn-primary button-prevent-multiple-submits">{{__('Gutschrift hinzufügen')}}</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{!! Form::close() !!}
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$( document ).ready(function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{!! Form::open(['url' => route('admin_payments_credit_create'), 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
{!! Form::open(['action' => route('admin_payments_credit_create'), 'class' => 'modal-content', 'enctype' => 'multipart/form-data']) !!}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
<td><div class="no-line-break">{{ formatDate($user_pay_credit->created_at) }}</div></td>
|
<td><div class="no-line-break">{{ formatDate($user_pay_credit->created_at) }}</div></td>
|
||||||
|
|
||||||
@if($user_pay_credit->shopping_order_id)
|
@if($user_pay_credit->shopping_order_id)
|
||||||
<td><a class="btn btn-secondary btn-xs" href="{{ route('admin_sales_users_detail', [$user_pay_credit->shopping_order_id]) }}"><i class="ion ion-md-eye"></i></a></td>
|
<td><a class="btn btn-secondary btn-xs" href="{{ route('admin_sales_detail', [$user_pay_credit->shopping_order_id]) }}"><i class="ion ion-md-eye"></i></a></td>
|
||||||
@else
|
@else
|
||||||
@if($user_pay_credit->status === 3 && $deleteTime = $user_pay_credit->deleteTime())
|
@if($user_pay_credit->status === 3 && $deleteTime = $user_pay_credit->deleteTime())
|
||||||
<td>
|
<td>
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<div class="td-entry-table-margin">
|
|
||||||
{!! $entry->badge !!}
|
|
||||||
|
|
||||||
@if($entry->link)
|
|
||||||
<a href="{{ $entry->link }}">
|
|
||||||
@else
|
|
||||||
<span>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{!! $entry->name !!} /
|
|
||||||
|
|
||||||
@if($entry->reference)
|
|
||||||
{!! $entry->reference !!} /
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->total)
|
|
||||||
({!! $entry->total !!})
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->date)
|
|
||||||
{!! $entry->date !!} /
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if(isset($entry->price_formatted))
|
|
||||||
<strong>{!! $entry->price_formatted !!} €</strong>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->link)
|
|
||||||
</a>
|
|
||||||
@else
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if(isset($entry->delete))
|
|
||||||
{!! $entry->delete !!}
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<div class="td-entry-table-margin">
|
|
||||||
{!! $entry->badge !!}
|
|
||||||
|
|
||||||
@if($entry->link)
|
|
||||||
<a href="{{ $entry->link }}">
|
|
||||||
@else
|
|
||||||
<span>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{!! $entry->name !!} /
|
|
||||||
|
|
||||||
@if($entry->reference)
|
|
||||||
{!! $entry->reference !!} /
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->total)
|
|
||||||
({!! $entry->total !!})
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->date)
|
|
||||||
{!! $entry->date !!} /
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if(isset($entry->price_formatted))
|
|
||||||
<strong>{!! $entry->price_formatted !!} €</strong>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if($entry->link)
|
|
||||||
</a>
|
|
||||||
@else
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@if(isset($entry->delete))
|
|
||||||
{!! $entry->delete !!}
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
@ -117,7 +117,7 @@
|
||||||
Zahlungen / erstellte Gutschriften
|
Zahlungen / erstellte Gutschriften
|
||||||
</h6>
|
</h6>
|
||||||
<div class="col-sm-6 mb-0 mt-2">
|
<div class="col-sm-6 mb-0 mt-2">
|
||||||
{!! Form::open(['url' => route('admin_payments_credit'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
{!! Form::open(['action' => route('admin_payments_credit'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
||||||
|
|
||||||
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
||||||
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@
|
||||||
Zahlungen / erstellte Gutschriften
|
Zahlungen / erstellte Gutschriften
|
||||||
</h6>
|
</h6>
|
||||||
<div class="col-sm-6 mb-0 mt-2">
|
<div class="col-sm-6 mb-0 mt-2">
|
||||||
{!! Form::open(['url' => route('admin_payments_credit'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
{!! Form::open(['action' => route('admin_payments_credit'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
||||||
|
|
||||||
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
||||||
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
Zahlungen / Rechnungen
|
Zahlungen / Rechnungen
|
||||||
</h6>
|
</h6>
|
||||||
<div class="col-sm-6 mb-0 mt-2">
|
<div class="col-sm-6 mb-0 mt-2">
|
||||||
{!! Form::open(['url' => route('admin_payments_invoice'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
{!! Form::open(['action' => route('admin_payments_invoice'), 'class' => 'form-horizontal', 'id'=>'form_filter_sales_year']) !!}
|
||||||
|
|
||||||
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
<label class="form-label" for="filter_sales_year">Filter Jahr</label>
|
||||||
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
<select class="custom-select" name="filter_sales_year" id="filter_sales_year">
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
</h6>
|
</h6>
|
||||||
{{-- <div class="col-sm-6 mb-0 mt-2">
|
{{-- <div class="col-sm-6 mb-0 mt-2">
|
||||||
{!! Form::open(['url' => route('admin_payments_paycredit'), 'class' => 'form-horizontal', 'id'=>'form_filter_user_status']) !!}
|
{!! Form::open(['action' => route('admin_payments_paycredit'), 'class' => 'form-horizontal', 'id'=>'form_filter_user_status']) !!}
|
||||||
<label class="form-label" for="filter_user_status">Filter User</label>
|
<label class="form-label" for="filter_user_status">Filter User</label>
|
||||||
<select class="custom-select" name="filter_user_status" id="filter_user_status">
|
<select class="custom-select" name="filter_user_status" id="filter_user_status">
|
||||||
<option value="all" @if($filter_user_status === 'all') selected @endif>alle</option>
|
<option value="all" @if($filter_user_status === 'all') selected @endif>alle</option>
|
||||||
|
|
|
||||||
107
resources/views/admin/payment/reminder/edit.blade.php
Normal file
107
resources/views/admin/payment/reminder/edit.blade.php
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@if ($errors->any())
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<h4 class="font-weight-bold py-2 mb-2">
|
||||||
|
{{ __('Erinnerung') }} {{ $reminder->id > 0 ? 'bearbeiten' : 'erstellen' }}
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="text-left mt-0 mb-2">
|
||||||
|
<a href="{{ route('admin_payments_reminder') }}" class="btn btn-default">{{ __('back') }}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card mb-2">
|
||||||
|
{!! Form::open(['action' => route('admin_payments_reminder_store',), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
|
<input type="hidden" name="id" value="@if($reminder->id>0){{$reminder->id}}@else new @endif">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col">
|
||||||
|
<label for="title" class="form-label">{{__('Titel')}}*</label>
|
||||||
|
{{ Form::text('title', $reminder->title, array('placeholder'=>__('Titel'), 'class'=>'form-control', 'required')) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col">
|
||||||
|
<label for="subject" class="form-label">{{__('Betreff')}}*</label>
|
||||||
|
{{ Form::text('subject', $reminder->subject, array('placeholder'=>__('Betreff'), 'class'=>'form-control', 'required')) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col">
|
||||||
|
<label for="message" class="form-label">{{__('Nachricht')}}</label>
|
||||||
|
{{ Form::textarea('message', $reminder->message, array('placeholder'=>__('Nachricht'), 'class'=>'form-control summernote-small')) }}
|
||||||
|
<p> <i>Platzhalter: {billing_first_name}, {billing_last_name}, {order_number}, {order_date}, {order_total}</i></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col">
|
||||||
|
<label for="interval" class="form-label">{{__('Interval (in Tagen nach der Bestellung)')}}*</label>
|
||||||
|
{{ Form::number('interval', $reminder->interval, array('placeholder'=>__('Interval'), 'class'=>'form-control', 'required')) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col">
|
||||||
|
<label for="clearingtype" class="form-label">{{__('Typ')}}*</label>
|
||||||
|
{{ Form::select('clearingtype', \App\Models\PaymentReminder::returnClearingtypes(), $reminder->clearingtype, array('placeholder'=>__('Typ'), 'class'=>'form-control custom-select', 'required')) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col-12">
|
||||||
|
<label class="custom-control custom-checkbox m-2">
|
||||||
|
{!! Form::checkbox('action', 'set_order_status_cancelled', $reminder->action == 'set_order_status_cancelled', ['class'=>'custom-control-input']) !!}
|
||||||
|
<span class="custom-control-label">Action: Bestellung auf "storniert" setzen</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group col-12">
|
||||||
|
<label class="custom-control custom-checkbox m-2">
|
||||||
|
{!! Form::checkbox('active', 1, $reminder->active, ['class'=>'custom-control-input']) !!}
|
||||||
|
<span class="custom-control-label">{{__('active')}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@if($reminder->id > 0)
|
||||||
|
<div class="float-right">
|
||||||
|
<a href="{{ route('admin_payments_reminder_delete', $reminder->id) }}" class="btn btn-danger btn-sm" onclick="return confirm('{{ __('Are you sure you want to delete this reminder?') }}')"><i class="fa fa-trash"></i> {{ __('delete') }}</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<div class="text-left mt-0 mb-2">
|
||||||
|
<button type="submit" class="btn btn-secondary">{{ __('save') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{!! Form::close() !!}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="text-left mt-2 mb-2">
|
||||||
|
<a href="{{ route('admin_payments_reminder') }}" class="btn btn-default">{{ __('back') }}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@endsection
|
||||||
582
resources/views/admin/payment/reminder/index.blade.php
Normal file
582
resources/views/admin/payment/reminder/index.blade.php
Normal file
|
|
@ -0,0 +1,582 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Optimierte Reminder Badge Styles */
|
||||||
|
.reminder-badge {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-badge:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-badge.badge-warning {
|
||||||
|
background: linear-gradient(45deg, #ffc107, #ffb300);
|
||||||
|
border: 1px solid #ffa000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-badge.badge-danger {
|
||||||
|
background: linear-gradient(45deg, #dc3545, #c82333);
|
||||||
|
border: 1px solid #bd2130;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-badge.badge-dark {
|
||||||
|
background: linear-gradient(45deg, #343a40, #23272b);
|
||||||
|
border: 1px solid #1d2124;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-badge.badge-light {
|
||||||
|
background: linear-gradient(45deg, #f8f9fa, #e9ecef);
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
color: #6c757d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip Verbesserungen */
|
||||||
|
.tooltip-inner {
|
||||||
|
background-color: #343a40;
|
||||||
|
color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.bs-tooltip-top .arrow::before {
|
||||||
|
border-top-color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.bs-tooltip-bottom .arrow::before {
|
||||||
|
border-bottom-color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reminder Datum Styling */
|
||||||
|
.reminder-date {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-date:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Countdown Styling */
|
||||||
|
.countdown-info {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgba(0,0,0,0.05);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-info:hover {
|
||||||
|
background: rgba(0,0,0,0.1);
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-info.text-info {
|
||||||
|
background: rgba(23, 162, 184, 0.1);
|
||||||
|
border: 1px solid rgba(23, 162, 184, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-info.text-danger {
|
||||||
|
background: rgba(220, 53, 69, 0.1);
|
||||||
|
border: 1px solid rgba(220, 53, 69, 0.2);
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-info.text-success {
|
||||||
|
background: rgba(40, 167, 69, 0.1);
|
||||||
|
border: 1px solid rgba(40, 167, 69, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-days {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #17a2b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pulse Animation für fällige Erinnerungen */
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
box-shadow: 0 0 0 10px rgba(220, 53, 69, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Anpassungen */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.reminder-badge {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-date {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-info {
|
||||||
|
font-size: 9px;
|
||||||
|
padding: 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown-days {
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info Box Styling */
|
||||||
|
.info-box {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box h5 {
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .feature-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .feature-list li {
|
||||||
|
padding: 8px 0;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .feature-list li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .feature-list li i {
|
||||||
|
margin-right: 10px;
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .workflow-steps {
|
||||||
|
background: rgba(255,255,255,0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .workflow-steps h6 {
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .step {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .step-number {
|
||||||
|
background: rgba(255,255,255,0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .cron-info {
|
||||||
|
background: rgba(255,255,255,0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box .cron-info code {
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title">
|
||||||
|
<i class="fas fa-envelope"></i> Erinnerungen
|
||||||
|
</h4>
|
||||||
|
<div class="float-right">
|
||||||
|
<a href="{{ route('admin_payments_reminder_create') }}" class="btn btn-sm btn-primary">
|
||||||
|
<span class="far fa-plus-circle"></span> Erinnerung hinzufügen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="card-datatable table-responsive pt-2">
|
||||||
|
<table class="datatables-style table table-striped table-bordered" id="datatable-pay-credit">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>{{__('Titel')}}</th>
|
||||||
|
<th>{{__('Interval') }}</th>
|
||||||
|
<th>{{__('Typ') }}</th>
|
||||||
|
<th>{{__('Action') }}</th>
|
||||||
|
<th>{{__('Aktiv') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
@foreach($reminders as $reminder)
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('admin_payments_reminder_edit', $reminder->id) }}" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>
|
||||||
|
</td>
|
||||||
|
<td>{{ $reminder->title }}</td>
|
||||||
|
<td>{{ $reminder->interval }}</td>
|
||||||
|
<td>{{ $reminder->getClearingtype() }}</td>
|
||||||
|
<td>{{ $reminder->action }}</td>
|
||||||
|
<td>{!! get_active_badge($reminder->active) !!}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<!-- Offene Zahlungen Übersicht -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title">
|
||||||
|
<i class="fas fa-clock"></i> Offene Zahlungen - Übersicht
|
||||||
|
</h4>
|
||||||
|
<div class="card-tools">
|
||||||
|
<span class="badge badge-primary">{{ $totalPayments }} offene Zahlungen</span>
|
||||||
|
<span class="badge badge-warning">{{ number_format($totalAmount, 2, ',', '.') }} € Gesamtbetrag</span>
|
||||||
|
</div>
|
||||||
|
<div class="float-right">
|
||||||
|
<a href="{{ route('admin_payments_reminder_logs') }}" class="btn btn-sm btn-info mr-2">
|
||||||
|
<i class="fas fa-chart-line"></i> Logs & Statistiken
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Detaillierte Tabelle -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped" id="payment-reminders-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Bestell-ID</th>
|
||||||
|
<th>Betrag</th>
|
||||||
|
<th>Erstellt am</th>
|
||||||
|
<th>Tage alt</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Zahlungsart</th>
|
||||||
|
<th>Versand</th>
|
||||||
|
<th>Erinnerung</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($detailedData as $payment)
|
||||||
|
<tr>
|
||||||
|
<td data-order="{{ $payment['order_id'] }}">
|
||||||
|
|
||||||
|
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{{ route('admin_sales_detail', $payment['order_id']) }}" target="_blank">
|
||||||
|
<i class="fa fa-eye"></i> {{ $payment['order_id'] }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<span class="text-danger font-weight-bold">
|
||||||
|
{{ number_format($payment['amount']/100, 2, ',', '.') }} €
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['created_at'] }}</td>
|
||||||
|
<td>
|
||||||
|
@if($payment['days_old'] > 30)
|
||||||
|
<span class="badge badge-danger">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@elseif($payment['days_old'] > 14)
|
||||||
|
<span class="badge badge-warning">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@else
|
||||||
|
<span class="badge badge-info">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['name'] }}</td>
|
||||||
|
<td>{{ $payment['email'] }}</td>
|
||||||
|
<td>
|
||||||
|
@if($payment['clearingtype'] == 'fnc')
|
||||||
|
<span class="badge badge-primary">{{ $payment['clearingtype_name'] }}</span>
|
||||||
|
@else
|
||||||
|
<span class="badge badge-warning">{{ $payment['clearingtype_name'] }}</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>{!! $payment['shipped'] !!}</td>
|
||||||
|
<td>
|
||||||
|
@if($payment['reminder'] > 0)
|
||||||
|
<div class="d-flex flex-column align-items-start">
|
||||||
|
<!-- Reminder Badge mit verbesserter Darstellung -->
|
||||||
|
<span class="badge badge-pill reminder-badge badge-{{ $payment['reminder'] == 1 ? 'warning' : ($payment['reminder'] == 2 ? 'danger' : 'dark') }} mb-1"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="top"
|
||||||
|
title="{{ $payment['reminder'] }}. Zahlungserinnerung gesendet">
|
||||||
|
<i class="fas fa-envelope-open-text mr-1"></i>
|
||||||
|
<strong>{{ $payment['reminder'] }}.</strong>
|
||||||
|
@if($payment['reminder'] == 1)
|
||||||
|
<i class="fas fa-exclamation-triangle ml-1"></i>
|
||||||
|
@elseif($payment['reminder'] >= 2)
|
||||||
|
<i class="fas fa-exclamation-circle ml-1"></i>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- Datum mit verbesserter Formatierung -->
|
||||||
|
@if($payment['reminder_date'])
|
||||||
|
<small class="text-muted reminder-date"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="bottom"
|
||||||
|
title="Letzte Erinnerung gesendet">
|
||||||
|
<i class="far fa-clock mr-1"></i>
|
||||||
|
{{ \Carbon\Carbon::parse($payment['reminder_date'])->diffForHumans() }}
|
||||||
|
</small>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Countdown für nächste Erinnerung -->
|
||||||
|
@if(isset($payment['countdown']) && $payment['countdown'])
|
||||||
|
@if($payment['countdown']['type'] == 'countdown')
|
||||||
|
<small class="text-info countdown-info mt-1"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="bottom"
|
||||||
|
title="Nächste Erinnerung am {{ \Carbon\Carbon::parse($payment['countdown']['next_reminder_date'])->format('d.m.Y') }}">
|
||||||
|
<i class="fas fa-hourglass-half mr-1"></i>
|
||||||
|
<span class="countdown-days">{{ $payment['countdown']['days_left'] }}</span> Tage
|
||||||
|
</small>
|
||||||
|
@elseif($payment['countdown']['type'] == 'overdue')
|
||||||
|
<small class="text-danger countdown-info mt-1"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="bottom"
|
||||||
|
title="Nächste Erinnerung war fällig am {{ \Carbon\Carbon::parse($payment['countdown']['next_reminder_date'])->format('d.m.Y') }}">
|
||||||
|
<i class="fas fa-exclamation-triangle mr-1"></i>
|
||||||
|
Fällig!
|
||||||
|
</small>
|
||||||
|
@elseif($payment['countdown']['type'] == 'completed')
|
||||||
|
<small class="text-success countdown-info mt-1"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="bottom"
|
||||||
|
title="Alle verfügbaren Erinnerungen wurden gesendet">
|
||||||
|
<i class="fas fa-check-circle mr-1"></i>
|
||||||
|
Alle gesendet
|
||||||
|
</small>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="badge badge-pill reminder-badge badge-light text-muted"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="top"
|
||||||
|
title="Noch keine Erinnerung gesendet">
|
||||||
|
<i class="fas fa-envelope mr-1"></i>
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a href="{{ route('admin_payments_reminder_action', ['action' => 'send_reminder', 'id' => $payment['payment_id']]) }}" class="btn btn-sm btn-outline-primary"
|
||||||
|
onclick="return confirm('Möchten Sie wirklich eine Zahlungserinnerung senden?')">
|
||||||
|
<i class="fas fa-envelope"></i> Erinnerung senden
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('admin_payments_reminder_action', ['action' => 'no_payment', 'id' => $payment['payment_id']]) }}" class="btn btn-sm btn-outline-danger"
|
||||||
|
onclick="return confirm('Soll die Zahlung als nicht bezahlt markiert werden?')">
|
||||||
|
<i class="fas fa-trash"></i> keine Zahlung
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="9" class="text-center text-muted">
|
||||||
|
<i class="fas fa-check-circle"></i> Keine offenen Zahlungen gefunden
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{-- <div class="info-box mt-4">
|
||||||
|
<h5><i class="fas fa-info-circle mr-2"></i>Zahlungserinnerungen System - Übersicht & Funktionsweise</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6><i class="fas fa-cogs mr-2"></i>System-Features:</h6>
|
||||||
|
<ul class="feature-list">
|
||||||
|
<li><i class="fas fa-check text-success"></i>Dynamisch konfigurierbare Erinnerungsintervalle</li>
|
||||||
|
<li><i class="fas fa-check text-success"></i>Automatische E-Mail-Versendung via Cron-Job</li>
|
||||||
|
<li><i class="fas fa-check text-success"></i>Intelligente Fälligkeitsberechnung</li>
|
||||||
|
<li><i class="fas fa-check text-success"></i>Detailliertes Logging & Statistiken</li>
|
||||||
|
<li><i class="fas fa-check text-success"></i>Manuelle & automatische Aktionen</li>
|
||||||
|
<li><i class="fas fa-check text-success"></i>Responsive Admin-Interface</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6><i class="fas fa-clock mr-2"></i>Workflow:</h6>
|
||||||
|
<div class="workflow-steps">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">1</span>
|
||||||
|
<span>Offene Zahlung wird erkannt</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">2</span>
|
||||||
|
<span>Intervall-basierte Fälligkeitsprüfung</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">3</span>
|
||||||
|
<span>Automatische E-Mail-Versendung</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">4</span>
|
||||||
|
<span>Logging & Status-Update</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">5</span>
|
||||||
|
<span>Nächste Erinnerung planen</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6><i class="fas fa-calendar-alt mr-2"></i>Reminder-Erstellung:</h6>
|
||||||
|
<p style="font-size: 14px; line-height: 1.5;">
|
||||||
|
Erstellen Sie neue Erinnerungen über den "Erinnerung hinzufügen" Button.
|
||||||
|
Jeder Reminder kann individuell konfiguriert werden mit:
|
||||||
|
</p>
|
||||||
|
<ul class="feature-list" style="font-size: 13px;">
|
||||||
|
<li><i class="fas fa-arrow-right text-info"></i>Titel & Beschreibung</li>
|
||||||
|
<li><i class="fas fa-arrow-right text-info"></i>Intervall in Tagen (z.B. 7, 14, 30)</li>
|
||||||
|
<li><i class="fas fa-arrow-right text-info"></i>Zahlungsart-Filter (FNC, PayPal, etc.)</li>
|
||||||
|
<li><i class="fas fa-arrow-right text-info"></i>E-Mail-Template & Betreff</li>
|
||||||
|
<li><i class="fas fa-arrow-right text-info"></i>Automatische Aktionen</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6><i class="fas fa-robot mr-2"></i>Automatisierung:</h6>
|
||||||
|
<div class="cron-info">
|
||||||
|
<strong>Cron-Job Konfiguration:</strong><br>
|
||||||
|
<code>0 9 * * *</code> php /path/to/artisan payments:reminders<br><br>
|
||||||
|
<strong>Ausführung:</strong> Täglich um 9:00 Uhr<br>
|
||||||
|
<strong>Funktion:</strong> Prüft alle aktiven Reminder und sendet fällige E-Mails
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<h6><i class="fas fa-chart-line mr-2"></i>Monitoring & Statistiken:</h6>
|
||||||
|
<p style="font-size: 14px; line-height: 1.5;">
|
||||||
|
Überwachen Sie die Performance Ihres Reminder-Systems über die "Logs & Statistiken" Seite.
|
||||||
|
Dort finden Sie detaillierte Auswertungen zu Versandraten, Erfolgsquoten,
|
||||||
|
durchschnittlichen Reaktionszeiten und mehr. Das System loggt jeden Schritt
|
||||||
|
automatisch für vollständige Transparenz.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Tooltips initialisieren
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
|
||||||
|
// DataTable für Payment Reminder Einstellungen
|
||||||
|
$('#payment-reminders-settings-table').DataTable({
|
||||||
|
"language": {
|
||||||
|
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/German.json"
|
||||||
|
},
|
||||||
|
"pageLength": 25,
|
||||||
|
"responsive": true
|
||||||
|
});
|
||||||
|
|
||||||
|
// DataTable für offene Zahlungen
|
||||||
|
$('#payment-reminders-table').DataTable({
|
||||||
|
"language": {
|
||||||
|
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/German.json"
|
||||||
|
},
|
||||||
|
"order": [[3, "desc"]], // Sortiere nach "Tage alt" absteigend
|
||||||
|
"pageLength": 50,
|
||||||
|
"responsive": true,
|
||||||
|
"columnDefs": [
|
||||||
|
{
|
||||||
|
"targets": [8], // Reminder Spalte
|
||||||
|
"orderable": true,
|
||||||
|
"searchable": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tooltips nach DataTable-Initialisierung neu initialisieren
|
||||||
|
$('#payment-reminders-table').on('draw.dt', function() {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendReminder(paymentId) {
|
||||||
|
if (confirm('Möchten Sie wirklich eine Zahlungserinnerung senden?')) {
|
||||||
|
// TODO: Implementiere Erinnerung senden
|
||||||
|
alert('Erinnerung für Payment ID ' + paymentId + ' würde gesendet werden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewDetails(paymentId) {
|
||||||
|
// TODO: Implementiere Detail-Ansicht
|
||||||
|
alert('Details für Payment ID ' + paymentId + ' würden angezeigt werden');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
333
resources/views/admin/payment/reminder/logs.blade.php
Normal file
333
resources/views/admin/payment/reminder/logs.blade.php
Normal file
|
|
@ -0,0 +1,333 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Statistik Cards */
|
||||||
|
.stats-card {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-number {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-label {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #6c757d;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log Tabelle */
|
||||||
|
.log-table {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-level {
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-level.info { background: rgba(23, 162, 184, 0.1); color: #17a2b8; }
|
||||||
|
.log-level.warning { background: rgba(255, 193, 7, 0.1); color: #ffc107; }
|
||||||
|
.log-level.error { background: rgba(220, 53, 69, 0.1); color: #dc3545; }
|
||||||
|
.log-level.notice { background: rgba(40, 167, 69, 0.1); color: #28a745; }
|
||||||
|
|
||||||
|
/* Filter Form */
|
||||||
|
.filter-form {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.stats-number {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-table {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h1 class="h3 mb-0">
|
||||||
|
<i class="fas fa-chart-line"></i> Payment Reminder Logs & Statistiken
|
||||||
|
</h1>
|
||||||
|
<a href="{{ route('admin_payments_reminder') }}" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Zurück zur Übersicht
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Statistiken Übersicht -->
|
||||||
|
{{-- <div class="row mb-4">
|
||||||
|
<!-- 7 Tage -->
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<div class="card stats-card bg-primary text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<div class="stats-number">{{ $stats7Days['summary']['total_logs'] }}</div>
|
||||||
|
<div class="stats-label">Logs (7 Tage)</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<small>
|
||||||
|
<i class="fas fa-envelope"></i> {{ $stats7Days['summary']['emails_sent'] }} gesendet |
|
||||||
|
<i class="fas fa-exclamation-triangle"></i> {{ $stats7Days['summary']['emails_failed'] }} fehlgeschlagen
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 30 Tage -->
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<div class="card stats-card bg-success text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<div class="stats-number">{{ $stats30Days['summary']['total_logs'] }}</div>
|
||||||
|
<div class="stats-label">Logs (30 Tage)</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<small>
|
||||||
|
<i class="fas fa-envelope"></i> {{ $stats30Days['summary']['emails_sent'] }} gesendet |
|
||||||
|
<i class="fas fa-exclamation-triangle"></i> {{ $stats30Days['summary']['emails_failed'] }} fehlgeschlagen
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 90 Tage -->
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<div class="card stats-card bg-info text-white">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<div class="stats-number">{{ $stats90Days['summary']['total_logs'] }}</div>
|
||||||
|
<div class="stats-label">Logs (90 Tage)</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<small>
|
||||||
|
<i class="fas fa-envelope"></i> {{ $stats90Days['summary']['emails_sent'] }} gesendet |
|
||||||
|
<i class="fas fa-exclamation-triangle"></i> {{ $stats90Days['summary']['emails_failed'] }} fehlgeschlagen
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
--}}
|
||||||
|
|
||||||
|
<!-- Filter -->
|
||||||
|
<div class="card filter-form">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title mb-3">
|
||||||
|
<i class="fas fa-filter"></i> Filter
|
||||||
|
</h5>
|
||||||
|
<form method="GET" action="{{ route('admin_payments_reminder_logs') }}" class="row">
|
||||||
|
<div class="col-md-3 mb-2">
|
||||||
|
<label for="order_id" class="form-label">Order ID</label>
|
||||||
|
<input type="number" class="form-control" id="order_id" name="order_id" value="{{ $orderId }}" placeholder="Order ID">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 mb-2">
|
||||||
|
<label for="action" class="form-label">Aktion</label>
|
||||||
|
<select class="form-control custom-select" id="action" name="action">
|
||||||
|
<option value="">Alle Aktionen</option>
|
||||||
|
<option value="email_sent" {{ $action == 'email_sent' ? 'selected' : '' }}>E-Mail gesendet</option>
|
||||||
|
<option value="email_exception" {{ $action == 'email_exception' ? 'selected' : '' }}>E-Mail Fehler</option>
|
||||||
|
<option value="reminder_completed" {{ $action == 'reminder_completed' ? 'selected' : '' }}>Erinnerung abgeschlossen</option>
|
||||||
|
<option value="action_completed" {{ $action == 'action_completed' ? 'selected' : '' }}>Aktion abgeschlossen</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 mb-2">
|
||||||
|
<label for="start_date" class="form-label">Von</label>
|
||||||
|
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ $startDate }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 mb-2">
|
||||||
|
<label for="end_date" class="form-label">Bis</label>
|
||||||
|
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ $endDate }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 mb-2 d-flex align-items-end">
|
||||||
|
<button type="submit" class="btn btn-primary me-2">
|
||||||
|
<i class="fas fa-search"></i> Filtern
|
||||||
|
</button>
|
||||||
|
<a href="{{ route('admin_payments_reminder_logs') }}" class="btn btn-outline-secondary">
|
||||||
|
<i class="fas fa-times"></i> Reset
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Logs Tabelle -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">
|
||||||
|
<i class="fas fa-list"></i>
|
||||||
|
@if($filteredLogs)
|
||||||
|
Gefilterte Logs ({{ $filteredLogs->count() }} Einträge)
|
||||||
|
@else
|
||||||
|
Neueste Logs ({{ $recentLogs->count() }} Einträge)
|
||||||
|
@endif
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped log-table" id="logs-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Datum</th>
|
||||||
|
<th>Aktion</th>
|
||||||
|
<th>Level</th>
|
||||||
|
<th>Model</th>
|
||||||
|
<th>Model ID</th>
|
||||||
|
<th>Nachricht</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse(($filteredLogs ?: $recentLogs) as $log)
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<small>{{ $log->created_at->format('d.m.Y H:i:s') }}</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge badge-secondary">{{ $log->action }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="log-level {{ $log->getLevelType() }}">
|
||||||
|
{{ ucfirst($log->getLevelType()) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<small>{{ $log->model ?: '-' }}</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if($log->model_id)
|
||||||
|
<a href="{{ route('admin_sales_detail', $log->model_id) }}" target="_blank" class="btn btn-sm btn-outline-primary">
|
||||||
|
{{ $log->model_id }}
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<small>-</small>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<small>{{ Str::limit($log->message, 100) }}</small>
|
||||||
|
@if(strlen($log->message) > 100)
|
||||||
|
<button type="button" class="btn btn-sm btn-link" data-toggle="tooltip" data-placement="top" title="{{ $log->message }}">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center text-muted">
|
||||||
|
<i class="fas fa-inbox"></i> Keine Logs gefunden
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Detaillierte Statistiken -->
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">
|
||||||
|
<i class="fas fa-chart-pie"></i> Aktionen (30 Tage)
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Aktion</th>
|
||||||
|
<th>Level</th>
|
||||||
|
<th>Anzahl</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($stats30Days['detailed_stats'] as $stat)
|
||||||
|
<tr>
|
||||||
|
<td><small>{{ $stat->action }}</small></td>
|
||||||
|
<td>
|
||||||
|
<span class="log-level {{ $stat->level == 2 ? 'info' : ($stat->level == 5 ? 'error' : 'notice') }}">
|
||||||
|
{{ $stat->level == 2 ? 'Info' : ($stat->level == 5 ? 'Error' : 'Notice') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td><strong>{{ $stat->count }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">
|
||||||
|
<i class="fas fa-chart-bar"></i> Erfolgsrate (30 Tage)
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
@php
|
||||||
|
$totalEmails = $stats30Days['summary']['emails_sent'] + $stats30Days['summary']['emails_failed'];
|
||||||
|
$successRate = $totalEmails > 0 ? round(($stats30Days['summary']['emails_sent'] / $totalEmails) * 100, 1) : 0;
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="display-4 text-success">{{ $successRate }}%</div>
|
||||||
|
<div class="text-muted">Erfolgsrate</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar bg-success" style="width: {{ $successRate }}%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<small class="text-muted">
|
||||||
|
{{ $stats30Days['summary']['emails_sent'] }} erfolgreich / {{ $totalEmails }} gesamt
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
// DataTable für Logs
|
||||||
|
$('#logs-table').DataTable({
|
||||||
|
"language": {
|
||||||
|
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/German.json"
|
||||||
|
},
|
||||||
|
"order": [[0, "desc"]], // Sortiere nach Datum absteigend
|
||||||
|
"pageLength": 50,
|
||||||
|
"responsive": true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tooltips initialisieren
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endsection
|
||||||
176
resources/views/admin/payment/reminder/overview.blade.php
Normal file
176
resources/views/admin/payment/reminder/overview.blade.php
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">
|
||||||
|
<i class="fas fa-clock"></i> Payment Reminders
|
||||||
|
</h3>
|
||||||
|
<div class="card-tools">
|
||||||
|
<span class="badge badge-primary">{{ $totalPayments }} offene Zahlungen</span>
|
||||||
|
<span class="badge badge-warning">{{ number_format($totalAmount, 2, ',', '.') }} € Gesamtbetrag</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<!-- Statistiken -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-info"><i class="fas fa-list"></i></span>
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">Offene Zahlungen</span>
|
||||||
|
<span class="info-box-number">{{ $totalPayments }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-warning"><i class="fas fa-euro-sign"></i></span>
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">Gesamtbetrag</span>
|
||||||
|
<span class="info-box-number">{{ number_format($totalAmount, 2, ',', '.') }} €</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-success"><i class="fas fa-credit-card"></i></span>
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">Zahlungsarten</span>
|
||||||
|
<span class="info-box-number">{{ count($clearingTypes) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-danger"><i class="fas fa-calendar"></i></span>
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">Letzte Aktualisierung</span>
|
||||||
|
<span class="info-box-number">{{ now()->format('d.m.Y H:i') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Übersicht nach Zahlungsarten -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
@foreach($summaryData as $clearingtype => $data)
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="small-box bg-info">
|
||||||
|
<div class="inner">
|
||||||
|
<h3>{{ $data['count'] }}</h3>
|
||||||
|
<p>{{ strtoupper($clearingtype) }} - {{ $data['interval'] }} Tage</p>
|
||||||
|
</div>
|
||||||
|
<div class="icon">
|
||||||
|
<i class="fas fa-credit-card"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Detaillierte Tabelle -->
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped" id="payment-reminders-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Zahlungsart</th>
|
||||||
|
<th>Intervall (Tage)</th>
|
||||||
|
<th>Bestell-ID</th>
|
||||||
|
<th>Zahlungs-ID</th>
|
||||||
|
<th>Betrag</th>
|
||||||
|
<th>Erstellt am</th>
|
||||||
|
<th>Tage alt</th>
|
||||||
|
<th>Grenzdatum</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($detailedData as $payment)
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="badge badge-primary">{{ strtoupper($payment['clearingtype']) }}</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['interval_days'] }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('admin_sales_detail', $payment['order_id']) }}" target="_blank">
|
||||||
|
#{{ $payment['order_id'] }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['payment_id'] }}</td>
|
||||||
|
<td>
|
||||||
|
<span class="text-danger font-weight-bold">
|
||||||
|
{{ number_format($payment['amount'], 2, ',', '.') }} €
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['created_at'] }}</td>
|
||||||
|
<td>
|
||||||
|
@if($payment['days_old'] > 30)
|
||||||
|
<span class="badge badge-danger">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@elseif($payment['days_old'] > 14)
|
||||||
|
<span class="badge badge-warning">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@else
|
||||||
|
<span class="badge badge-info">{{ $payment['days_old'] }} Tage</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>{{ $payment['date_limit'] }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
||||||
|
onclick="sendReminder({{ $payment['payment_id'] }})">
|
||||||
|
<i class="fas fa-envelope"></i> Erinnerung senden
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-info"
|
||||||
|
onclick="viewDetails({{ $payment['payment_id'] }})">
|
||||||
|
<i class="fas fa-eye"></i> Details
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="9" class="text-center text-muted">
|
||||||
|
<i class="fas fa-check-circle"></i> Keine offenen Zahlungen gefunden
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#payment-reminders-table').DataTable({
|
||||||
|
"language": {
|
||||||
|
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/German.json"
|
||||||
|
},
|
||||||
|
"order": [[6, "desc"]], // Sortiere nach "Tage alt" absteigend
|
||||||
|
"pageLength": 25,
|
||||||
|
"responsive": true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendReminder(paymentId) {
|
||||||
|
if (confirm('Möchten Sie wirklich eine Zahlungserinnerung senden?')) {
|
||||||
|
// TODO: Implementiere Erinnerung senden
|
||||||
|
alert('Erinnerung für Payment ID ' + paymentId + ' würde gesendet werden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewDetails(paymentId) {
|
||||||
|
// TODO: Implementiere Detail-Ansicht
|
||||||
|
alert('Details für Payment ID ' + paymentId + ' würden angezeigt werden');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
{{ __('Create/Edit Produkt') }}
|
{{ __('Create/Edit Produkt') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_product_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
{!! Form::open(['action' => route('admin_product_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
|
||||||
<input type="hidden" name="id" id="id" value="@if($product->id>0){{$product->id}}@else new @endif">
|
<input type="hidden" name="id" id="id" value="@if($product->id>0){{$product->id}}@else new @endif">
|
||||||
|
|
||||||
<div class="text-left mt-0 mb-2">
|
<div class="text-left mt-0 mb-2">
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
{{ __('Create/Edit Promotion') }}
|
{{ __('Create/Edit Promotion') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
{!! Form::open(['url' => route('admin_promotion_detail', $promotion->id), 'class' => 'form-horizontal']) !!}
|
{!! Form::open(['action' => route('admin_promotion_detail', $promotion->id), 'class' => 'form-horizontal']) !!}
|
||||||
<input type="hidden" name="id" id="id" value="@if($promotion->id>0){{$promotion->id}}@else new @endif">
|
<input type="hidden" name="id" id="id" value="@if($promotion->id>0){{$promotion->id}}@else new @endif">
|
||||||
|
|
||||||
<div class="text-left mt-0 mb-2">
|
<div class="text-left mt-0 mb-2">
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
<!-- Status -->
|
<!-- Status -->
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3 mb-1">
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-1">
|
||||||
<strong class="mr-2">Status:</strong>
|
<strong class="mr-2">Status:</strong>
|
||||||
<span class="text-big">
|
<span class="text-big">
|
||||||
{!! \App\Services\Payment::getPaymentForTypeBadge($shopping_order) !!}
|
{!! \App\Services\Payment::getPaymentForTypeBadge($shopping_order) !!}
|
||||||
{!! \App\Services\Payment::getShoppingOrderBadge($shopping_order) !!}
|
{!! \App\Services\Payment::getShoppingOrderBadge($shopping_order) !!}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 mb-1">
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-1">
|
||||||
<strong class="mr-2">Versand:</strong>
|
<strong class="mr-2">Versand:</strong>
|
||||||
@if($isAdmin)
|
@if($isAdmin)
|
||||||
<button type="button" class="btn btn-sm btn-{{$shopping_order->getShippedColor()}}" data-toggle="modal" data-target="#modals-shipped"
|
<button type="button" class="btn btn-sm btn-{{$shopping_order->getShippedColor()}}" data-toggle="modal" data-target="#modals-shipped"
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 mb-1">
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-1">
|
||||||
<strong class="mr-2">Rechnung:</strong>
|
<strong class="mr-2">Rechnung:</strong>
|
||||||
@if($isAdmin)
|
@if($isAdmin)
|
||||||
@if(App\Services\Invoice::isInvoice($shopping_order))
|
@if(App\Services\Invoice::isInvoice($shopping_order))
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3 mb-1">
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-1">
|
||||||
@if ($isAdmin)
|
@if ($isAdmin)
|
||||||
<strong class="mr-2">Lieferschein:</strong>
|
<strong class="mr-2">Lieferschein:</strong>
|
||||||
@if (App\Services\Invoice::isDelivery($shopping_order))
|
@if (App\Services\Invoice::isDelivery($shopping_order))
|
||||||
|
|
@ -70,10 +70,14 @@
|
||||||
|
|
||||||
<a href="{{ route('storage_file', [$shopping_order->id, 'invoice_delivery', 'download']) }}"
|
<a href="{{ route('storage_file', [$shopping_order->id, 'invoice_delivery', 'download']) }}"
|
||||||
class="btn btn-dark btn-sm"><i class="fa fa-file-download"></i><i class="fa fa-file-download"></i></a>
|
class="btn btn-dark btn-sm"><i class="fa fa-file-download"></i><i class="fa fa-file-download"></i></a>
|
||||||
@endif
|
|
||||||
|
<a href="{{ route('admin_sales_send_logistic_mail', [$shopping_order->id]) }}"
|
||||||
|
class="btn btn-info btn-sm"><i class="fa fa-envelope"></i></a>
|
||||||
|
@endif
|
||||||
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -96,9 +100,8 @@
|
||||||
{{$shopping_order->getFormattedTotalShipping()}} €
|
{{$shopping_order->getFormattedTotalShipping()}} €
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 mb-3">
|
<div class="col-md-3 mb-3">
|
||||||
{{-- <div class="text-muted small">Points gesamt</div>
|
<div class="text-muted small">White Label</div>
|
||||||
{{ $shopping_order->points }}
|
{{ $shopping_order->user_white_label ? 'Ja' : 'Nein' }}
|
||||||
--}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -134,7 +137,7 @@
|
||||||
<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
|
<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
|
||||||
data-id="{{$shopping_order->shopping_user->id}}"
|
data-id="{{$shopping_order->shopping_user->id}}"
|
||||||
data-action="shopping-user-is-like-member"
|
data-action="shopping-user-is-like-member"
|
||||||
data-back="{{route('admin_sales_customers_detail', [$shopping_order->id])}}"
|
data-back="{{route('admin_sales_detail', [$shopping_order->id])}}"
|
||||||
data-modal="modal-xl"
|
data-modal="modal-xl"
|
||||||
data-route="{{route('modal_load')}}"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>
|
data-route="{{route('modal_load')}}"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>
|
||||||
@else
|
@else
|
||||||
|
|
|
||||||
15
resources/views/admin/sales/detail.blade.php
Normal file
15
resources/views/admin/sales/detail.blade.php
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h4 class="font-weight-bold py-2 mb-2">
|
||||||
|
<a href="{{route('admin_sales')}}" class="btn btn-sm btn-default float-right">zurück</a>
|
||||||
|
@if($isView === 'sales_customer')
|
||||||
|
{{ __('Bestellung Kunde') }} <span class="text-muted">#{{$shopping_order->id}}</span>
|
||||||
|
@elseif($isView === 'sales_user')
|
||||||
|
{{ __('Bestellung Vertriebspartner') }} <span class="text-muted">#{{$shopping_order->id}}</span>
|
||||||
|
@endif
|
||||||
|
</h4>
|
||||||
|
@include('admin.sales._detail')
|
||||||
|
<a href="{{route('admin_sales')}}" class="btn btn-sm btn-default mt-2 float-right">zurück</a>
|
||||||
|
|
||||||
|
@endsection
|
||||||
128
resources/views/admin/sales/index.blade.php
Normal file
128
resources/views/admin/sales/index.blade.php
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
@extends('layouts.layout-2')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="font-weight-bold py-2 mb-2">
|
||||||
|
{{ __('Bestellungen Kunden') }}
|
||||||
|
</h4>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="form-row align-items-center">
|
||||||
|
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-2">
|
||||||
|
<label class="form-label" for="filter_member_id">Filter zugewiesener Vertriebspartner</label>
|
||||||
|
<select class="custom-select" name="filter_member_id" id="filter_member_id">
|
||||||
|
<option value="">Filter aus</option>
|
||||||
|
@foreach($filter_members as $member)
|
||||||
|
<option value="{{$member->id}}" @if(get_user_attr('filter_member_id') == $member->id) selected @endif>{{$member->first_name}} {{$member->last_name}} |{{$member->email}}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-2">
|
||||||
|
<label class="form-label" for="filter_txaction">Filter Status</label>
|
||||||
|
<select class="custom-select" name="filter_txaction" id="filter_txaction">
|
||||||
|
<option value="">Filter aus</option>
|
||||||
|
@foreach(\App\Services\Payment::$txaction_text as $id=>$name)
|
||||||
|
<option value="{{$id}}" @if(get_user_attr('filter_txaction') == $id) selected @endif>{{$name}}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-3 mb-2">
|
||||||
|
<label class="form-label" for="filter_shipped">Filter Versand</label>
|
||||||
|
<select class="custom-select" name="filter_shipped" id="filter_shipped">
|
||||||
|
<option value="">Filter aus</option>
|
||||||
|
@foreach(\App\Models\ShoppingOrder::$shippedTypes as $id=>$name)
|
||||||
|
<option value="{{$id}}" @if(get_user_attr('filter_shipped') === $id) selected @endif>{{$name}}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-2 mb-2">
|
||||||
|
<label class="form-label" for="filter_art">Filter Art</label>
|
||||||
|
<select class="custom-select" name="filter_art" id="filter_art">
|
||||||
|
<option value="">Filter aus</option>
|
||||||
|
@foreach(\App\Services\PaymentService::$txaction_art as $id=>$name)
|
||||||
|
<option value="{{$id}}" @if(get_user_attr('filter_art') == $id) selected @endif>{{$name}}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-1 col-md-1 col-lg-1 mb-2 mt-4">
|
||||||
|
<a href="{{ route('admin_sales') }}?reset=filter" data-toggle="tooltip" data-placement="top" title="Reset Filter" class="btn icon-btn btn-sm btn-outline-dark float-right">
|
||||||
|
<span class="fa fa-sync"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="card-datatable table-responsive">
|
||||||
|
<table class="datatable-customers table table-striped table-bordered" id="datatable-customers">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>{{__('Datum')}}</th>
|
||||||
|
<th>{{__('Betrag')}}</th>
|
||||||
|
<th>{{__('Zahlung')}}</th>
|
||||||
|
<th>{{__('Status')}}</th>
|
||||||
|
<th>{{__('Versand')}}</th>
|
||||||
|
<th>{{__('Art')}}</th>
|
||||||
|
<th>{{__('First name')}}</th>
|
||||||
|
<th>{{__('Last name')}}</th>
|
||||||
|
<th>{{__('E-Mail')}}</th>
|
||||||
|
<th>{{__('zugewiesener Vertriebspartner')}}</th>
|
||||||
|
<th>{{__('Rf-Nr.')}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$( document ).ready(function() {
|
||||||
|
var oTable = $('#datatable-customers').DataTable({
|
||||||
|
"processing": true,
|
||||||
|
"serverSide": true,
|
||||||
|
ajax: {
|
||||||
|
url: '{!! route( 'admin_sales_datatable') !!}',
|
||||||
|
data: function(d) {
|
||||||
|
d.filter_member_id = $('select[name=filter_member_id]').val();
|
||||||
|
d.filter_txaction = $('select[name=filter_txaction]').val();
|
||||||
|
d.filter_art = $('select[name=filter_art]').val();
|
||||||
|
d.filter_shipped = $('select[name=filter_shipped]').val();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"order": [[0, "desc" ]],
|
||||||
|
"columns": [
|
||||||
|
{ data: 'id', searchable: false },
|
||||||
|
{ data: 'created_at', name: 'shopping_orders.created_at' },
|
||||||
|
{ data: 'total_shipping', name: 'total_shipping' },
|
||||||
|
{ data: 'payment', name: 'payment', orderable: false },
|
||||||
|
{ data: 'txaction', name: 'txaction' },
|
||||||
|
{ data: 'shipped', name: 'shipped' },
|
||||||
|
{ data: 'payment_for', name: 'payment_for' },
|
||||||
|
{ data: 'shopping_user.billing_firstname', name: 'shopping_user.billing_firstname' },
|
||||||
|
{ data: 'shopping_user.billing_lastname', name: 'shopping_user.billing_lastname' },
|
||||||
|
{ data: 'shopping_user.billing_email', name: 'shopping_user.billing_email' },
|
||||||
|
{ data: 'member_id', name: 'member_id', searchable: false, orderable: false },
|
||||||
|
{ data: 'reference', name: 'reference' },
|
||||||
|
],
|
||||||
|
"bLengthChange": false,
|
||||||
|
"iDisplayLength": 100,
|
||||||
|
"language": {
|
||||||
|
"url": "/js/German.json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#filter_member_id').on('change', function(){
|
||||||
|
oTable.draw();
|
||||||
|
});
|
||||||
|
$('#filter_txaction').on('change', function(){
|
||||||
|
oTable.draw();
|
||||||
|
});
|
||||||
|
$('#filter_art').on('change', function(){
|
||||||
|
oTable.draw();
|
||||||
|
});
|
||||||
|
$('#filter_shipped').on('change', function(){
|
||||||
|
oTable.draw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue