Add coupons, newsletter, country-based shipping, sale prices, USP bar
Deploy to Production (witstore.wende.it) / deploy (push) Successful in 8s

- Gutscheincodes: DB-Verwaltung (%, €-Rabatt, Mindestbestellwert, Ablauf),
  Eingabefeld im Checkout, Admin unter Marketing → Gutscheine
- Newsletter: Double-Opt-In per E-Mail, Formular im Footer,
  Admin-Liste mit CSV-Export
- Länderzonen-Versand: DE / DACH / EU / WORLD, Versandkosten nach
  Lieferland dynamisch berechnet, Coupon-Rabatt in Bestellung gespeichert
- Sale-Preise: sale_price auf Produkten, durchgestrichener UVP auf
  Produktkarte, Sonderangebote-Sektion auf Startseite
- USP-Leiste auf Startseite: Versand, Zahlung, Rückgabe, Service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 11:07:14 +02:00
co-authored by Claude Sonnet 4.6
parent 5dad8b9324
commit 092dae6085
27 changed files with 782 additions and 51 deletions
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Coupon extends Model
{
protected $fillable = ['code','type','value','min_order_value','expires_at','max_uses','used_count','active'];
protected $casts = [
'active' => 'boolean',
'expires_at' => 'datetime',
'value' => 'decimal:2',
'min_order_value' => 'decimal:2',
];
public static function findValid(string $code): ?self
{
return self::where('code', strtoupper(trim($code)))
->where('active', true)
->where(fn($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>=', now()))
->where(fn($q) => $q->whereNull('max_uses')->orWhereColumn('used_count', '<', 'max_uses'))
->first();
}
public function calcDiscount(float $subtotal): float
{
if ($this->min_order_value && $subtotal < $this->min_order_value) {
return 0.0;
}
if ($this->type === 'percent') {
return round($subtotal * $this->value / 100, 2);
}
return min((float) $this->value, $subtotal);
}
}